@cajoa/core 0.12.0 → 0.13.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/index.cjs +92 -6
- package/dist/index.d.cts +16 -3
- package/dist/index.d.ts +16 -3
- package/dist/index.js +91 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
createContext: () => createContext,
|
|
30
30
|
createEffect: () => createEffect,
|
|
31
31
|
createMemo: () => createMemo,
|
|
32
|
+
createResource: () => createResource,
|
|
32
33
|
createRoot: () => createRoot,
|
|
33
34
|
createSignal: () => createSignal,
|
|
34
35
|
getRenderer: () => getRenderer,
|
|
@@ -259,6 +260,84 @@ function createMemo(fn) {
|
|
|
259
260
|
return value;
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
// src/reactivity/resource.ts
|
|
264
|
+
function isPromiseLike(value) {
|
|
265
|
+
return typeof value?.then === "function";
|
|
266
|
+
}
|
|
267
|
+
function createResource(a, b) {
|
|
268
|
+
const hasSource = typeof b === "function";
|
|
269
|
+
const source = hasSource ? a : () => true;
|
|
270
|
+
const fetcher = hasSource ? b : a;
|
|
271
|
+
const [data, setData] = createSignal(void 0);
|
|
272
|
+
const [failure, setFailure] = createSignal(null);
|
|
273
|
+
const [loading, setLoading] = createSignal(false);
|
|
274
|
+
const [version, setVersion] = createSignal(0);
|
|
275
|
+
let run = 0;
|
|
276
|
+
const finish = (id, outcome) => {
|
|
277
|
+
if (id !== run) return;
|
|
278
|
+
batch(() => {
|
|
279
|
+
setLoading(false);
|
|
280
|
+
if ("error" in outcome) {
|
|
281
|
+
setFailure({ error: outcome.error });
|
|
282
|
+
} else {
|
|
283
|
+
setFailure(null);
|
|
284
|
+
setData(() => outcome.value);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
createEffect(() => {
|
|
289
|
+
const s = source();
|
|
290
|
+
version();
|
|
291
|
+
run++;
|
|
292
|
+
const id = run;
|
|
293
|
+
onCleanup(() => {
|
|
294
|
+
run++;
|
|
295
|
+
});
|
|
296
|
+
if (s === false || s === null || s === void 0) {
|
|
297
|
+
batch(() => {
|
|
298
|
+
setLoading(false);
|
|
299
|
+
setFailure(null);
|
|
300
|
+
setData(() => void 0);
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
setLoading(true);
|
|
305
|
+
setFailure(null);
|
|
306
|
+
let result;
|
|
307
|
+
try {
|
|
308
|
+
result = untrack(() => fetcher(s));
|
|
309
|
+
} catch (error) {
|
|
310
|
+
finish(id, { error });
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
if (isPromiseLike(result)) {
|
|
314
|
+
result.then(
|
|
315
|
+
(value) => finish(id, { value }),
|
|
316
|
+
(error) => finish(id, { error })
|
|
317
|
+
);
|
|
318
|
+
} else {
|
|
319
|
+
finish(id, { value: result });
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
const resource = (() => {
|
|
323
|
+
const failed = failure();
|
|
324
|
+
if (failed) throw failed.error;
|
|
325
|
+
return data();
|
|
326
|
+
});
|
|
327
|
+
resource.loading = loading;
|
|
328
|
+
resource.error = () => failure()?.error;
|
|
329
|
+
return [
|
|
330
|
+
resource,
|
|
331
|
+
{
|
|
332
|
+
refetch: () => setVersion((v) => v + 1),
|
|
333
|
+
mutate: (value) => batch(() => {
|
|
334
|
+
setFailure(null);
|
|
335
|
+
setData(() => value);
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
];
|
|
339
|
+
}
|
|
340
|
+
|
|
262
341
|
// src/renderer/index.ts
|
|
263
342
|
var current = null;
|
|
264
343
|
function setRenderer(renderer) {
|
|
@@ -294,11 +373,21 @@ function h(tag, props, ...children) {
|
|
|
294
373
|
if (onRef) untrack(() => onRef(el));
|
|
295
374
|
return el;
|
|
296
375
|
}
|
|
376
|
+
function materialize(value) {
|
|
377
|
+
if (typeof value !== "function") return value;
|
|
378
|
+
const holder = getRenderer().createFragment();
|
|
379
|
+
appendChildren(holder, [value]);
|
|
380
|
+
return holder;
|
|
381
|
+
}
|
|
297
382
|
function toNodes(value) {
|
|
298
383
|
const r = getRenderer();
|
|
299
384
|
const out = [];
|
|
300
385
|
for (const v of [value].flat(Infinity)) {
|
|
301
386
|
if (v == null || typeof v === "boolean") continue;
|
|
387
|
+
if (typeof v === "function") {
|
|
388
|
+
out.push(materialize(v));
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
302
391
|
out.push(r.isNode(v) ? v : r.createText(String(v)));
|
|
303
392
|
}
|
|
304
393
|
return out;
|
|
@@ -400,11 +489,7 @@ function For(props) {
|
|
|
400
489
|
|
|
401
490
|
// src/components/error-boundary.ts
|
|
402
491
|
function resolve2(value) {
|
|
403
|
-
|
|
404
|
-
while (typeof current2 === "function") {
|
|
405
|
-
current2 = current2();
|
|
406
|
-
}
|
|
407
|
-
return current2;
|
|
492
|
+
return typeof value === "function" ? value() : value;
|
|
408
493
|
}
|
|
409
494
|
function ErrorBoundary(props) {
|
|
410
495
|
const [version, setVersion] = createSignal(0);
|
|
@@ -434,7 +519,7 @@ function ErrorBoundary(props) {
|
|
|
434
519
|
let early = null;
|
|
435
520
|
const content = untrack(
|
|
436
521
|
() => catchError(
|
|
437
|
-
() => resolve2(props.children ?? null),
|
|
522
|
+
() => materialize(resolve2(props.children ?? null)),
|
|
438
523
|
(error) => {
|
|
439
524
|
if (creating) early = { error };
|
|
440
525
|
else fail(error);
|
|
@@ -477,6 +562,7 @@ function Fragment(props) {
|
|
|
477
562
|
createContext,
|
|
478
563
|
createEffect,
|
|
479
564
|
createMemo,
|
|
565
|
+
createResource,
|
|
480
566
|
createRoot,
|
|
481
567
|
createSignal,
|
|
482
568
|
getRenderer,
|
package/dist/index.d.cts
CHANGED
|
@@ -17,6 +17,19 @@ declare function useContext<T>(ctx: Context<T>): T;
|
|
|
17
17
|
|
|
18
18
|
declare function createMemo<T>(fn: () => T): () => T;
|
|
19
19
|
|
|
20
|
+
interface Resource<T> {
|
|
21
|
+
(): T | undefined;
|
|
22
|
+
loading: () => boolean;
|
|
23
|
+
error: () => unknown;
|
|
24
|
+
}
|
|
25
|
+
interface ResourceActions<T> {
|
|
26
|
+
refetch: () => void;
|
|
27
|
+
mutate(value: T | undefined): void;
|
|
28
|
+
}
|
|
29
|
+
type ResourceTuple<T> = [Resource<T>, ResourceActions<T>];
|
|
30
|
+
declare function createResource<T>(fetcher: () => T | Promise<T>): ResourceTuple<T>;
|
|
31
|
+
declare function createResource<T, S>(source: () => S | false | null | undefined, fetcher: (source: S) => T | Promise<T>): ResourceTuple<T>;
|
|
32
|
+
|
|
20
33
|
type HostNode = object;
|
|
21
34
|
interface Renderer<N = any> {
|
|
22
35
|
createElement(tag: string): N;
|
|
@@ -55,7 +68,7 @@ declare function ErrorBoundary(props: {
|
|
|
55
68
|
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
56
69
|
children?: Lazy<Child>;
|
|
57
70
|
onError?: (error: unknown) => void;
|
|
58
|
-
}): () =>
|
|
71
|
+
}): () => unknown;
|
|
59
72
|
|
|
60
73
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
61
74
|
declare const jsxs: typeof jsx;
|
|
@@ -76,5 +89,5 @@ declare function Fragment(props: {
|
|
|
76
89
|
declare function setRenderer(renderer: Renderer): void;
|
|
77
90
|
declare function getRenderer(): Renderer;
|
|
78
91
|
|
|
79
|
-
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
80
|
-
export type { Child, Context, HostNode, Renderer };
|
|
92
|
+
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
93
|
+
export type { Child, Context, HostNode, Renderer, Resource, ResourceActions };
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,19 @@ declare function useContext<T>(ctx: Context<T>): T;
|
|
|
17
17
|
|
|
18
18
|
declare function createMemo<T>(fn: () => T): () => T;
|
|
19
19
|
|
|
20
|
+
interface Resource<T> {
|
|
21
|
+
(): T | undefined;
|
|
22
|
+
loading: () => boolean;
|
|
23
|
+
error: () => unknown;
|
|
24
|
+
}
|
|
25
|
+
interface ResourceActions<T> {
|
|
26
|
+
refetch: () => void;
|
|
27
|
+
mutate(value: T | undefined): void;
|
|
28
|
+
}
|
|
29
|
+
type ResourceTuple<T> = [Resource<T>, ResourceActions<T>];
|
|
30
|
+
declare function createResource<T>(fetcher: () => T | Promise<T>): ResourceTuple<T>;
|
|
31
|
+
declare function createResource<T, S>(source: () => S | false | null | undefined, fetcher: (source: S) => T | Promise<T>): ResourceTuple<T>;
|
|
32
|
+
|
|
20
33
|
type HostNode = object;
|
|
21
34
|
interface Renderer<N = any> {
|
|
22
35
|
createElement(tag: string): N;
|
|
@@ -55,7 +68,7 @@ declare function ErrorBoundary(props: {
|
|
|
55
68
|
fallback: Child | ((error: unknown, reset: () => void) => Child);
|
|
56
69
|
children?: Lazy<Child>;
|
|
57
70
|
onError?: (error: unknown) => void;
|
|
58
|
-
}): () =>
|
|
71
|
+
}): () => unknown;
|
|
59
72
|
|
|
60
73
|
declare function jsx(type: any, props: Record<string, any> | null): any;
|
|
61
74
|
declare const jsxs: typeof jsx;
|
|
@@ -76,5 +89,5 @@ declare function Fragment(props: {
|
|
|
76
89
|
declare function setRenderer(renderer: Renderer): void;
|
|
77
90
|
declare function getRenderer(): Renderer;
|
|
78
91
|
|
|
79
|
-
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
80
|
-
export type { Child, Context, HostNode, Renderer };
|
|
92
|
+
export { ErrorBoundary, For, Fragment, JSX, Show, batch, catchError, createContext, createEffect, createMemo, createResource, createRoot, createSignal, getRenderer, h, jsx, jsxDEV, jsxs, onCleanup, onMount, provide, render, setRenderer, untrack, useContext };
|
|
93
|
+
export type { Child, Context, HostNode, Renderer, Resource, ResourceActions };
|
package/dist/index.js
CHANGED
|
@@ -211,6 +211,84 @@ function createMemo(fn) {
|
|
|
211
211
|
return value;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
// src/reactivity/resource.ts
|
|
215
|
+
function isPromiseLike(value) {
|
|
216
|
+
return typeof value?.then === "function";
|
|
217
|
+
}
|
|
218
|
+
function createResource(a, b) {
|
|
219
|
+
const hasSource = typeof b === "function";
|
|
220
|
+
const source = hasSource ? a : () => true;
|
|
221
|
+
const fetcher = hasSource ? b : a;
|
|
222
|
+
const [data, setData] = createSignal(void 0);
|
|
223
|
+
const [failure, setFailure] = createSignal(null);
|
|
224
|
+
const [loading, setLoading] = createSignal(false);
|
|
225
|
+
const [version, setVersion] = createSignal(0);
|
|
226
|
+
let run = 0;
|
|
227
|
+
const finish = (id, outcome) => {
|
|
228
|
+
if (id !== run) return;
|
|
229
|
+
batch(() => {
|
|
230
|
+
setLoading(false);
|
|
231
|
+
if ("error" in outcome) {
|
|
232
|
+
setFailure({ error: outcome.error });
|
|
233
|
+
} else {
|
|
234
|
+
setFailure(null);
|
|
235
|
+
setData(() => outcome.value);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
createEffect(() => {
|
|
240
|
+
const s = source();
|
|
241
|
+
version();
|
|
242
|
+
run++;
|
|
243
|
+
const id = run;
|
|
244
|
+
onCleanup(() => {
|
|
245
|
+
run++;
|
|
246
|
+
});
|
|
247
|
+
if (s === false || s === null || s === void 0) {
|
|
248
|
+
batch(() => {
|
|
249
|
+
setLoading(false);
|
|
250
|
+
setFailure(null);
|
|
251
|
+
setData(() => void 0);
|
|
252
|
+
});
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
setLoading(true);
|
|
256
|
+
setFailure(null);
|
|
257
|
+
let result;
|
|
258
|
+
try {
|
|
259
|
+
result = untrack(() => fetcher(s));
|
|
260
|
+
} catch (error) {
|
|
261
|
+
finish(id, { error });
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (isPromiseLike(result)) {
|
|
265
|
+
result.then(
|
|
266
|
+
(value) => finish(id, { value }),
|
|
267
|
+
(error) => finish(id, { error })
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
finish(id, { value: result });
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
const resource = (() => {
|
|
274
|
+
const failed = failure();
|
|
275
|
+
if (failed) throw failed.error;
|
|
276
|
+
return data();
|
|
277
|
+
});
|
|
278
|
+
resource.loading = loading;
|
|
279
|
+
resource.error = () => failure()?.error;
|
|
280
|
+
return [
|
|
281
|
+
resource,
|
|
282
|
+
{
|
|
283
|
+
refetch: () => setVersion((v) => v + 1),
|
|
284
|
+
mutate: (value) => batch(() => {
|
|
285
|
+
setFailure(null);
|
|
286
|
+
setData(() => value);
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
];
|
|
290
|
+
}
|
|
291
|
+
|
|
214
292
|
// src/renderer/index.ts
|
|
215
293
|
var current = null;
|
|
216
294
|
function setRenderer(renderer) {
|
|
@@ -246,11 +324,21 @@ function h(tag, props, ...children) {
|
|
|
246
324
|
if (onRef) untrack(() => onRef(el));
|
|
247
325
|
return el;
|
|
248
326
|
}
|
|
327
|
+
function materialize(value) {
|
|
328
|
+
if (typeof value !== "function") return value;
|
|
329
|
+
const holder = getRenderer().createFragment();
|
|
330
|
+
appendChildren(holder, [value]);
|
|
331
|
+
return holder;
|
|
332
|
+
}
|
|
249
333
|
function toNodes(value) {
|
|
250
334
|
const r = getRenderer();
|
|
251
335
|
const out = [];
|
|
252
336
|
for (const v of [value].flat(Infinity)) {
|
|
253
337
|
if (v == null || typeof v === "boolean") continue;
|
|
338
|
+
if (typeof v === "function") {
|
|
339
|
+
out.push(materialize(v));
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
254
342
|
out.push(r.isNode(v) ? v : r.createText(String(v)));
|
|
255
343
|
}
|
|
256
344
|
return out;
|
|
@@ -352,11 +440,7 @@ function For(props) {
|
|
|
352
440
|
|
|
353
441
|
// src/components/error-boundary.ts
|
|
354
442
|
function resolve2(value) {
|
|
355
|
-
|
|
356
|
-
while (typeof current2 === "function") {
|
|
357
|
-
current2 = current2();
|
|
358
|
-
}
|
|
359
|
-
return current2;
|
|
443
|
+
return typeof value === "function" ? value() : value;
|
|
360
444
|
}
|
|
361
445
|
function ErrorBoundary(props) {
|
|
362
446
|
const [version, setVersion] = createSignal(0);
|
|
@@ -386,7 +470,7 @@ function ErrorBoundary(props) {
|
|
|
386
470
|
let early = null;
|
|
387
471
|
const content = untrack(
|
|
388
472
|
() => catchError(
|
|
389
|
-
() => resolve2(props.children ?? null),
|
|
473
|
+
() => materialize(resolve2(props.children ?? null)),
|
|
390
474
|
(error) => {
|
|
391
475
|
if (creating) early = { error };
|
|
392
476
|
else fail(error);
|
|
@@ -428,6 +512,7 @@ export {
|
|
|
428
512
|
createContext,
|
|
429
513
|
createEffect,
|
|
430
514
|
createMemo,
|
|
515
|
+
createResource,
|
|
431
516
|
createRoot,
|
|
432
517
|
createSignal,
|
|
433
518
|
getRenderer,
|