fict 0.0.13 → 0.0.14
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/advanced.cjs +88 -0
- package/dist/advanced.cjs.map +1 -0
- package/dist/advanced.d.cts +3 -0
- package/dist/advanced.d.ts +3 -0
- package/dist/advanced.js +3 -0
- package/dist/advanced.js.map +1 -0
- package/dist/chunk-5AWNWCDT.js +121 -0
- package/dist/chunk-5AWNWCDT.js.map +1 -0
- package/dist/index.cjs +137 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3 -0
- package/dist/plus.cjs +7 -26
- package/dist/plus.cjs.map +1 -1
- package/dist/plus.d.cts +3 -4
- package/dist/plus.d.ts +3 -4
- package/dist/plus.js +4 -118
- package/dist/plus.js.map +1 -1
- package/package.json +8 -3
- package/src/advanced.ts +57 -0
- package/src/index.ts +74 -0
- package/src/plus.ts +28 -7
- package/src/resource.ts +2 -1
- package/src/store.ts +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var advanced = require('@fictjs/runtime/advanced');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "createAttributeBinding", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () { return advanced.createAttributeBinding; }
|
|
10
|
+
});
|
|
11
|
+
Object.defineProperty(exports, "createChildBinding", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return advanced.createChildBinding; }
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "createClassBinding", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return advanced.createClassBinding; }
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports, "createContext", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return advanced.createContext; }
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports, "createRenderEffect", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return advanced.createRenderEffect; }
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(exports, "createScope", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return advanced.createScope; }
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(exports, "createSelector", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () { return advanced.createSelector; }
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(exports, "createShow", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
get: function () { return advanced.createShow; }
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(exports, "createSignal", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get: function () { return advanced.createSignal; }
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(exports, "createStyleBinding", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () { return advanced.createStyleBinding; }
|
|
46
|
+
});
|
|
47
|
+
Object.defineProperty(exports, "createTextBinding", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
get: function () { return advanced.createTextBinding; }
|
|
50
|
+
});
|
|
51
|
+
Object.defineProperty(exports, "createVersionedSignal", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
get: function () { return advanced.createVersionedSignal; }
|
|
54
|
+
});
|
|
55
|
+
Object.defineProperty(exports, "effectScope", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
get: function () { return advanced.effectScope; }
|
|
58
|
+
});
|
|
59
|
+
Object.defineProperty(exports, "getDevtoolsHook", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: function () { return advanced.getDevtoolsHook; }
|
|
62
|
+
});
|
|
63
|
+
Object.defineProperty(exports, "hasContext", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
get: function () { return advanced.hasContext; }
|
|
66
|
+
});
|
|
67
|
+
Object.defineProperty(exports, "isReactive", {
|
|
68
|
+
enumerable: true,
|
|
69
|
+
get: function () { return advanced.isReactive; }
|
|
70
|
+
});
|
|
71
|
+
Object.defineProperty(exports, "runInScope", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
get: function () { return advanced.runInScope; }
|
|
74
|
+
});
|
|
75
|
+
Object.defineProperty(exports, "setCycleProtectionOptions", {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
get: function () { return advanced.setCycleProtectionOptions; }
|
|
78
|
+
});
|
|
79
|
+
Object.defineProperty(exports, "unwrap", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
get: function () { return advanced.unwrap; }
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(exports, "useContext", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
get: function () { return advanced.useContext; }
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=advanced.cjs.map
|
|
88
|
+
//# sourceMappingURL=advanced.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"advanced.cjs","sourcesContent":[]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { Context, FictDevtoolsHook, ProviderProps, ReactiveScope, Signal, VersionedSignal, VersionedSignalOptions, createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isReactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
|
|
2
|
+
import '@fictjs/runtime/jsx-dev-runtime';
|
|
3
|
+
import '@fictjs/runtime/jsx-runtime';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { Context, FictDevtoolsHook, ProviderProps, ReactiveScope, Signal, VersionedSignal, VersionedSignalOptions, createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isReactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
|
|
2
|
+
import '@fictjs/runtime/jsx-dev-runtime';
|
|
3
|
+
import '@fictjs/runtime/jsx-runtime';
|
package/dist/advanced.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isReactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
|
|
2
|
+
//# sourceMappingURL=advanced.js.map
|
|
3
|
+
//# sourceMappingURL=advanced.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"advanced.js","sourcesContent":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createSignal } from '@fictjs/runtime/advanced';
|
|
2
|
+
|
|
3
|
+
// src/store.ts
|
|
4
|
+
var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
var ITERATE_KEY = Symbol("iterate");
|
|
8
|
+
function getSignal(target, prop) {
|
|
9
|
+
let signals = SIGNAL_CACHE.get(target);
|
|
10
|
+
if (!signals) {
|
|
11
|
+
signals = {};
|
|
12
|
+
SIGNAL_CACHE.set(target, signals);
|
|
13
|
+
}
|
|
14
|
+
if (!signals[prop]) {
|
|
15
|
+
const initial = prop === ITERATE_KEY ? 0 : target[prop];
|
|
16
|
+
signals[prop] = createSignal(initial);
|
|
17
|
+
}
|
|
18
|
+
return signals[prop];
|
|
19
|
+
}
|
|
20
|
+
function triggerIteration(target) {
|
|
21
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
22
|
+
if (signals && signals[ITERATE_KEY]) {
|
|
23
|
+
const current = signals[ITERATE_KEY]();
|
|
24
|
+
signals[ITERATE_KEY](current + 1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function $store(initialValue) {
|
|
28
|
+
if (typeof initialValue !== "object" || initialValue === null) {
|
|
29
|
+
return initialValue;
|
|
30
|
+
}
|
|
31
|
+
if (PROXY_CACHE.has(initialValue)) {
|
|
32
|
+
return PROXY_CACHE.get(initialValue);
|
|
33
|
+
}
|
|
34
|
+
const proxy = new Proxy(initialValue, {
|
|
35
|
+
get(target, prop, receiver) {
|
|
36
|
+
const signal = getSignal(target, prop);
|
|
37
|
+
const trackedValue = signal();
|
|
38
|
+
const currentValue = Reflect.get(target, prop, receiver ?? proxy);
|
|
39
|
+
if (currentValue !== trackedValue) {
|
|
40
|
+
signal(currentValue);
|
|
41
|
+
}
|
|
42
|
+
if (typeof currentValue === "function") {
|
|
43
|
+
let boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
44
|
+
if (!boundMethods) {
|
|
45
|
+
boundMethods = /* @__PURE__ */ new Map();
|
|
46
|
+
BOUND_METHOD_CACHE.set(target, boundMethods);
|
|
47
|
+
}
|
|
48
|
+
const cached = boundMethods.get(prop);
|
|
49
|
+
if (cached && cached.ref === currentValue) {
|
|
50
|
+
return cached.bound;
|
|
51
|
+
}
|
|
52
|
+
const bound = currentValue.bind(receiver ?? proxy);
|
|
53
|
+
boundMethods.set(prop, { ref: currentValue, bound });
|
|
54
|
+
return bound;
|
|
55
|
+
}
|
|
56
|
+
if (typeof currentValue === "object" && currentValue !== null) {
|
|
57
|
+
return $store(currentValue);
|
|
58
|
+
}
|
|
59
|
+
return currentValue;
|
|
60
|
+
},
|
|
61
|
+
set(target, prop, newValue, receiver) {
|
|
62
|
+
const oldValue = Reflect.get(target, prop, receiver);
|
|
63
|
+
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
64
|
+
if (oldValue === newValue && hadKey) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
const result = Reflect.set(target, prop, newValue, receiver);
|
|
68
|
+
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
69
|
+
if (boundMethods && boundMethods.has(prop)) {
|
|
70
|
+
boundMethods.delete(prop);
|
|
71
|
+
}
|
|
72
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
73
|
+
if (signals && signals[prop]) {
|
|
74
|
+
signals[prop](newValue);
|
|
75
|
+
}
|
|
76
|
+
if (!hadKey) {
|
|
77
|
+
triggerIteration(target);
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(target) && prop !== "length") {
|
|
80
|
+
const signals2 = SIGNAL_CACHE.get(target);
|
|
81
|
+
if (signals2 && signals2.length) {
|
|
82
|
+
signals2.length(target.length);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(target) && prop === "length") {
|
|
86
|
+
triggerIteration(target);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
},
|
|
90
|
+
deleteProperty(target, prop) {
|
|
91
|
+
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
92
|
+
const result = Reflect.deleteProperty(target, prop);
|
|
93
|
+
if (result && hadKey) {
|
|
94
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
95
|
+
if (signals && signals[prop]) {
|
|
96
|
+
signals[prop](void 0);
|
|
97
|
+
}
|
|
98
|
+
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
99
|
+
if (boundMethods && boundMethods.has(prop)) {
|
|
100
|
+
boundMethods.delete(prop);
|
|
101
|
+
}
|
|
102
|
+
triggerIteration(target);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
},
|
|
106
|
+
ownKeys(target) {
|
|
107
|
+
getSignal(target, ITERATE_KEY)();
|
|
108
|
+
return Reflect.ownKeys(target);
|
|
109
|
+
},
|
|
110
|
+
has(target, prop) {
|
|
111
|
+
getSignal(target, prop)();
|
|
112
|
+
return Reflect.has(target, prop);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
PROXY_CACHE.set(initialValue, proxy);
|
|
116
|
+
return proxy;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { $store };
|
|
120
|
+
//# sourceMappingURL=chunk-5AWNWCDT.js.map
|
|
121
|
+
//# sourceMappingURL=chunk-5AWNWCDT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/store.ts"],"names":["signals"],"mappings":";;;AAQA,IAAM,WAAA,uBAAkB,OAAA,EAAyB;AACjD,IAAM,YAAA,uBAAmB,OAAA,EAA0D;AACnF,IAAM,kBAAA,uBAAyB,OAAA,EAAwD;AACvF,IAAM,WAAA,GAAc,OAAO,SAAS,CAAA;AAEpC,SAAS,SAAA,CAAU,QAAgB,IAAA,EAAwC;AACzE,EAAA,IAAI,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACrC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,EAAC;AACX,IAAA,YAAA,CAAa,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,EAClC;AACA,EAAA,IAAI,CAAC,OAAA,CAAQ,IAAI,CAAA,EAAG;AAClB,IAAA,MAAM,OAAA,GAAU,IAAA,KAAS,WAAA,GAAc,CAAA,GAAK,OAA4C,IAAI,CAAA;AAC5F,IAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,YAAA,CAAa,OAAO,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,QAAQ,IAAI,CAAA;AACrB;AAEA,SAAS,iBAAiB,MAAA,EAAgB;AACxC,EAAA,MAAM,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACvC,EAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,WAAW,CAAA,EAAG;AACnC,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,WAAW,CAAA,EAAE;AACrC,IAAA,OAAA,CAAQ,WAAW,CAAA,CAAE,OAAA,GAAU,CAAC,CAAA;AAAA,EAClC;AACF;AAEO,SAAS,OAAyB,YAAA,EAAoB;AAC3D,EAAA,IAAI,OAAO,YAAA,KAAiB,QAAA,IAAY,YAAA,KAAiB,IAAA,EAAM;AAC7D,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACjC,IAAA,OAAO,WAAA,CAAY,IAAI,YAAY,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,YAAA,EAAc;AAAA,IACpC,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,QAAA,EAAU;AAG1B,MAAA,MAAM,MAAA,GAAS,SAAA,CAAU,MAAA,EAAQ,IAAI,CAAA;AACrC,MAAA,MAAM,eAAe,MAAA,EAAO;AAE5B,MAAA,MAAM,eAAe,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,YAAY,KAAK,CAAA;AAChE,MAAA,IAAI,iBAAiB,YAAA,EAAc;AAIjC,QAAA,MAAA,CAAO,YAAY,CAAA;AAAA,MACrB;AAEA,MAAA,IAAI,OAAO,iBAAiB,UAAA,EAAY;AACtC,QAAA,IAAI,YAAA,GAAe,kBAAA,CAAmB,GAAA,CAAI,MAAM,CAAA;AAChD,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,YAAA,uBAAmB,GAAA,EAAI;AACvB,UAAA,kBAAA,CAAmB,GAAA,CAAI,QAAQ,YAAY,CAAA;AAAA,QAC7C;AACA,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA;AACpC,QAAA,IAAI,MAAA,IAAU,MAAA,CAAO,GAAA,KAAQ,YAAA,EAAc;AACzC,UAAA,OAAO,MAAA,CAAO,KAAA;AAAA,QAChB;AAEA,QAAA,MAAM,KAAA,GAAS,YAAA,CAAuB,IAAA,CAAK,QAAA,IAAY,KAAK,CAAA;AAC5D,QAAA,YAAA,CAAa,IAAI,IAAA,EAAM,EAAE,GAAA,EAAK,YAAA,EAAuB,OAAO,CAAA;AAC5D,QAAA,OAAO,KAAA;AAAA,MACT;AAGA,MAAA,IAAI,OAAO,YAAA,KAAiB,QAAA,IAAY,YAAA,KAAiB,IAAA,EAAM;AAC7D,QAAA,OAAO,OAAO,YAAuC,CAAA;AAAA,MACvD;AAGA,MAAA,OAAO,YAAA;AAAA,IACT,CAAA;AAAA,IAEA,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU;AACpC,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,MAAM,QAAQ,CAAA;AACnD,MAAA,MAAM,SAAS,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,QAAQ,IAAI,CAAA;AAGhE,MAAA,IAAI,QAAA,KAAa,YAAY,MAAA,EAAQ;AACnC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,MAAM,SAAS,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,UAAU,QAAQ,CAAA;AAG3D,MAAA,MAAM,YAAA,GAAe,kBAAA,CAAmB,GAAA,CAAI,MAAM,CAAA;AAClD,MAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1C,QAAA,YAAA,CAAa,OAAO,IAAI,CAAA;AAAA,MAC1B;AAGA,MAAA,MAAM,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACvC,MAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC5B,QAAA,OAAA,CAAQ,IAAI,EAAE,QAAQ,CAAA;AAAA,MACxB;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,MACzB;AAIA,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IAAK,SAAS,QAAA,EAAU;AAC9C,QAAA,MAAMA,QAAAA,GAAU,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACvC,QAAA,IAAIA,QAAAA,IAAWA,SAAQ,MAAA,EAAQ;AAC7B,UAAAA,QAAAA,CAAQ,MAAA,CAAQ,MAAA,CAAyC,MAAM,CAAA;AAAA,QACjE;AAAA,MACF;AAIA,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IAAK,SAAS,QAAA,EAAU;AAC9C,QAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,MACzB;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,cAAA,CAAe,QAAQ,IAAA,EAAM;AAC3B,MAAA,MAAM,SAAS,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,QAAQ,IAAI,CAAA;AAChE,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,cAAA,CAAe,MAAA,EAAQ,IAAI,CAAA;AAElD,MAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,QAAA,MAAM,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACvC,QAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC5B,UAAA,OAAA,CAAQ,IAAI,EAAE,MAAS,CAAA;AAAA,QACzB;AAGA,QAAA,MAAM,YAAA,GAAe,kBAAA,CAAmB,GAAA,CAAI,MAAM,CAAA;AAClD,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1C,UAAA,YAAA,CAAa,OAAO,IAAI,CAAA;AAAA,QAC1B;AAEA,QAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,MACzB;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,QAAQ,MAAA,EAAQ;AACd,MAAA,SAAA,CAAU,MAAA,EAAQ,WAAW,CAAA,EAAE;AAC/B,MAAA,OAAO,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAAA,IAC/B,CAAA;AAAA,IAEA,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,SAAA,CAAU,MAAA,EAAQ,IAAI,CAAA,EAAE;AACxB,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAAA,IACjC;AAAA,GACD,CAAA;AAED,EAAA,WAAA,CAAY,GAAA,CAAI,cAAc,KAAK,CAAA;AACnC,EAAA,OAAO,KAAA;AACT","file":"chunk-5AWNWCDT.js","sourcesContent":["import { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\ntype AnyFn = (...args: unknown[]) => unknown\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\nconst PROXY_CACHE = new WeakMap<object, unknown>()\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\nconst ITERATE_KEY = Symbol('iterate')\n\nfunction getSignal(target: object, prop: string | symbol): Signal<unknown> {\n let signals = SIGNAL_CACHE.get(target)\n if (!signals) {\n signals = {}\n SIGNAL_CACHE.set(target, signals)\n }\n if (!signals[prop]) {\n const initial = prop === ITERATE_KEY ? 0 : (target as Record<string | symbol, unknown>)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\nfunction triggerIteration(target: object) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[ITERATE_KEY]) {\n const current = signals[ITERATE_KEY]() as number\n signals[ITERATE_KEY](current + 1)\n }\n}\n\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n if (PROXY_CACHE.has(initialValue)) {\n return PROXY_CACHE.get(initialValue) as T\n }\n\n const proxy = new Proxy(initialValue, {\n get(target, prop, receiver) {\n // Always touch the signal so reference changes to this property are tracked,\n // even if the value is an object we proxy further.\n const signal = getSignal(target, prop)\n const trackedValue = signal()\n\n const currentValue = Reflect.get(target, prop, receiver ?? proxy)\n if (currentValue !== trackedValue) {\n // If the value has changed (e.g. via direct mutation of the underlying object not via proxy),\n // we update the signal to keep it in sync.\n // Note: This is a bit of a heuristic. Ideally all mutations go through proxy.\n signal(currentValue)\n }\n\n if (typeof currentValue === 'function') {\n let boundMethods = BOUND_METHOD_CACHE.get(target)\n if (!boundMethods) {\n boundMethods = new Map()\n BOUND_METHOD_CACHE.set(target, boundMethods)\n }\n const cached = boundMethods.get(prop)\n if (cached && cached.ref === currentValue) {\n return cached.bound\n }\n\n const bound = (currentValue as AnyFn).bind(receiver ?? proxy)\n boundMethods.set(prop, { ref: currentValue as AnyFn, bound })\n return bound\n }\n\n // If the value is an object/array, we recursively wrap it in a store\n if (typeof currentValue === 'object' && currentValue !== null) {\n return $store(currentValue as Record<string, unknown>)\n }\n\n // For primitives (and functions), we return the signal value (which tracks the read)\n return currentValue\n },\n\n set(target, prop, newValue, receiver) {\n const oldValue = Reflect.get(target, prop, receiver)\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n\n // If value hasn't changed, do nothing\n if (oldValue === newValue && hadKey) {\n return true\n }\n\n const result = Reflect.set(target, prop, newValue, receiver)\n\n // IMPORTANT: Clear bound method cache BEFORE updating the signal\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n // Update the signal if it exists\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](newValue)\n }\n\n // If new property, trigger iteration update\n if (!hadKey) {\n triggerIteration(target)\n }\n\n // Ensure array length subscribers are notified even if the native push/pop\n // doesn't trigger a separate set trap for \"length\" (defensive).\n if (Array.isArray(target) && prop !== 'length') {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals.length) {\n signals.length((target as unknown as { length: number }).length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n // But usually 'length' is set explicitly or handled by the runtime.\n if (Array.isArray(target) && prop === 'length') {\n triggerIteration(target)\n }\n\n return result\n },\n\n deleteProperty(target, prop) {\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n const result = Reflect.deleteProperty(target, prop)\n\n if (result && hadKey) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](undefined)\n }\n\n // Clear bound method cache\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n triggerIteration(target)\n }\n\n return result\n },\n\n ownKeys(target) {\n getSignal(target, ITERATE_KEY)()\n return Reflect.ownKeys(target)\n },\n\n has(target, prop) {\n getSignal(target, prop)()\n return Reflect.has(target, prop)\n },\n })\n\n PROXY_CACHE.set(initialValue, proxy)\n return proxy\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,146 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var runtime = require('@fictjs/runtime');
|
|
4
|
+
var advanced = require('@fictjs/runtime/advanced');
|
|
4
5
|
|
|
6
|
+
// src/index.ts
|
|
7
|
+
var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
var ITERATE_KEY = Symbol("iterate");
|
|
11
|
+
function getSignal(target, prop) {
|
|
12
|
+
let signals = SIGNAL_CACHE.get(target);
|
|
13
|
+
if (!signals) {
|
|
14
|
+
signals = {};
|
|
15
|
+
SIGNAL_CACHE.set(target, signals);
|
|
16
|
+
}
|
|
17
|
+
if (!signals[prop]) {
|
|
18
|
+
const initial = prop === ITERATE_KEY ? 0 : target[prop];
|
|
19
|
+
signals[prop] = advanced.createSignal(initial);
|
|
20
|
+
}
|
|
21
|
+
return signals[prop];
|
|
22
|
+
}
|
|
23
|
+
function triggerIteration(target) {
|
|
24
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
25
|
+
if (signals && signals[ITERATE_KEY]) {
|
|
26
|
+
const current = signals[ITERATE_KEY]();
|
|
27
|
+
signals[ITERATE_KEY](current + 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function $store(initialValue) {
|
|
31
|
+
if (typeof initialValue !== "object" || initialValue === null) {
|
|
32
|
+
return initialValue;
|
|
33
|
+
}
|
|
34
|
+
if (PROXY_CACHE.has(initialValue)) {
|
|
35
|
+
return PROXY_CACHE.get(initialValue);
|
|
36
|
+
}
|
|
37
|
+
const proxy = new Proxy(initialValue, {
|
|
38
|
+
get(target, prop, receiver) {
|
|
39
|
+
const signal = getSignal(target, prop);
|
|
40
|
+
const trackedValue = signal();
|
|
41
|
+
const currentValue = Reflect.get(target, prop, receiver ?? proxy);
|
|
42
|
+
if (currentValue !== trackedValue) {
|
|
43
|
+
signal(currentValue);
|
|
44
|
+
}
|
|
45
|
+
if (typeof currentValue === "function") {
|
|
46
|
+
let boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
47
|
+
if (!boundMethods) {
|
|
48
|
+
boundMethods = /* @__PURE__ */ new Map();
|
|
49
|
+
BOUND_METHOD_CACHE.set(target, boundMethods);
|
|
50
|
+
}
|
|
51
|
+
const cached = boundMethods.get(prop);
|
|
52
|
+
if (cached && cached.ref === currentValue) {
|
|
53
|
+
return cached.bound;
|
|
54
|
+
}
|
|
55
|
+
const bound = currentValue.bind(receiver ?? proxy);
|
|
56
|
+
boundMethods.set(prop, { ref: currentValue, bound });
|
|
57
|
+
return bound;
|
|
58
|
+
}
|
|
59
|
+
if (typeof currentValue === "object" && currentValue !== null) {
|
|
60
|
+
return $store(currentValue);
|
|
61
|
+
}
|
|
62
|
+
return currentValue;
|
|
63
|
+
},
|
|
64
|
+
set(target, prop, newValue, receiver) {
|
|
65
|
+
const oldValue = Reflect.get(target, prop, receiver);
|
|
66
|
+
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
67
|
+
if (oldValue === newValue && hadKey) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const result = Reflect.set(target, prop, newValue, receiver);
|
|
71
|
+
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
72
|
+
if (boundMethods && boundMethods.has(prop)) {
|
|
73
|
+
boundMethods.delete(prop);
|
|
74
|
+
}
|
|
75
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
76
|
+
if (signals && signals[prop]) {
|
|
77
|
+
signals[prop](newValue);
|
|
78
|
+
}
|
|
79
|
+
if (!hadKey) {
|
|
80
|
+
triggerIteration(target);
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(target) && prop !== "length") {
|
|
83
|
+
const signals2 = SIGNAL_CACHE.get(target);
|
|
84
|
+
if (signals2 && signals2.length) {
|
|
85
|
+
signals2.length(target.length);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (Array.isArray(target) && prop === "length") {
|
|
89
|
+
triggerIteration(target);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
},
|
|
93
|
+
deleteProperty(target, prop) {
|
|
94
|
+
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
95
|
+
const result = Reflect.deleteProperty(target, prop);
|
|
96
|
+
if (result && hadKey) {
|
|
97
|
+
const signals = SIGNAL_CACHE.get(target);
|
|
98
|
+
if (signals && signals[prop]) {
|
|
99
|
+
signals[prop](void 0);
|
|
100
|
+
}
|
|
101
|
+
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
102
|
+
if (boundMethods && boundMethods.has(prop)) {
|
|
103
|
+
boundMethods.delete(prop);
|
|
104
|
+
}
|
|
105
|
+
triggerIteration(target);
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
},
|
|
109
|
+
ownKeys(target) {
|
|
110
|
+
getSignal(target, ITERATE_KEY)();
|
|
111
|
+
return Reflect.ownKeys(target);
|
|
112
|
+
},
|
|
113
|
+
has(target, prop) {
|
|
114
|
+
getSignal(target, prop)();
|
|
115
|
+
return Reflect.has(target, prop);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
PROXY_CACHE.set(initialValue, proxy);
|
|
119
|
+
return proxy;
|
|
120
|
+
}
|
|
5
121
|
|
|
6
|
-
|
|
122
|
+
Object.defineProperty(exports, "$memo", {
|
|
123
|
+
enumerable: true,
|
|
124
|
+
get: function () { return runtime.createMemo; }
|
|
125
|
+
});
|
|
126
|
+
Object.defineProperty(exports, "createScope", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
get: function () { return advanced.createScope; }
|
|
129
|
+
});
|
|
130
|
+
Object.defineProperty(exports, "createSelector", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
get: function () { return advanced.createSelector; }
|
|
133
|
+
});
|
|
134
|
+
Object.defineProperty(exports, "runInScope", {
|
|
135
|
+
enumerable: true,
|
|
136
|
+
get: function () { return advanced.runInScope; }
|
|
137
|
+
});
|
|
138
|
+
exports.$store = $store;
|
|
7
139
|
Object.keys(runtime).forEach(function (k) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
140
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
141
|
+
enumerable: true,
|
|
142
|
+
get: function () { return runtime[k]; }
|
|
143
|
+
});
|
|
12
144
|
});
|
|
13
145
|
//# sourceMappingURL=index.cjs.map
|
|
14
146
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs","sourcesContent":[]}
|
|
1
|
+
{"version":3,"sources":["../src/store.ts"],"names":["createSignal","signals"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\ntype AnyFn = (...args: unknown[]) => unknown\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\nconst PROXY_CACHE = new WeakMap<object, unknown>()\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\nconst ITERATE_KEY = Symbol('iterate')\n\nfunction getSignal(target: object, prop: string | symbol): Signal<unknown> {\n let signals = SIGNAL_CACHE.get(target)\n if (!signals) {\n signals = {}\n SIGNAL_CACHE.set(target, signals)\n }\n if (!signals[prop]) {\n const initial = prop === ITERATE_KEY ? 0 : (target as Record<string | symbol, unknown>)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\nfunction triggerIteration(target: object) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[ITERATE_KEY]) {\n const current = signals[ITERATE_KEY]() as number\n signals[ITERATE_KEY](current + 1)\n }\n}\n\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n if (PROXY_CACHE.has(initialValue)) {\n return PROXY_CACHE.get(initialValue) as T\n }\n\n const proxy = new Proxy(initialValue, {\n get(target, prop, receiver) {\n // Always touch the signal so reference changes to this property are tracked,\n // even if the value is an object we proxy further.\n const signal = getSignal(target, prop)\n const trackedValue = signal()\n\n const currentValue = Reflect.get(target, prop, receiver ?? proxy)\n if (currentValue !== trackedValue) {\n // If the value has changed (e.g. via direct mutation of the underlying object not via proxy),\n // we update the signal to keep it in sync.\n // Note: This is a bit of a heuristic. Ideally all mutations go through proxy.\n signal(currentValue)\n }\n\n if (typeof currentValue === 'function') {\n let boundMethods = BOUND_METHOD_CACHE.get(target)\n if (!boundMethods) {\n boundMethods = new Map()\n BOUND_METHOD_CACHE.set(target, boundMethods)\n }\n const cached = boundMethods.get(prop)\n if (cached && cached.ref === currentValue) {\n return cached.bound\n }\n\n const bound = (currentValue as AnyFn).bind(receiver ?? proxy)\n boundMethods.set(prop, { ref: currentValue as AnyFn, bound })\n return bound\n }\n\n // If the value is an object/array, we recursively wrap it in a store\n if (typeof currentValue === 'object' && currentValue !== null) {\n return $store(currentValue as Record<string, unknown>)\n }\n\n // For primitives (and functions), we return the signal value (which tracks the read)\n return currentValue\n },\n\n set(target, prop, newValue, receiver) {\n const oldValue = Reflect.get(target, prop, receiver)\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n\n // If value hasn't changed, do nothing\n if (oldValue === newValue && hadKey) {\n return true\n }\n\n const result = Reflect.set(target, prop, newValue, receiver)\n\n // IMPORTANT: Clear bound method cache BEFORE updating the signal\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n // Update the signal if it exists\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](newValue)\n }\n\n // If new property, trigger iteration update\n if (!hadKey) {\n triggerIteration(target)\n }\n\n // Ensure array length subscribers are notified even if the native push/pop\n // doesn't trigger a separate set trap for \"length\" (defensive).\n if (Array.isArray(target) && prop !== 'length') {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals.length) {\n signals.length((target as unknown as { length: number }).length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n // But usually 'length' is set explicitly or handled by the runtime.\n if (Array.isArray(target) && prop === 'length') {\n triggerIteration(target)\n }\n\n return result\n },\n\n deleteProperty(target, prop) {\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n const result = Reflect.deleteProperty(target, prop)\n\n if (result && hadKey) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](undefined)\n }\n\n // Clear bound method cache\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n triggerIteration(target)\n }\n\n return result\n },\n\n ownKeys(target) {\n getSignal(target, ITERATE_KEY)()\n return Reflect.ownKeys(target)\n },\n\n has(target, prop) {\n getSignal(target, prop)()\n return Reflect.has(target, prop)\n },\n })\n\n PROXY_CACHE.set(initialValue, proxy)\n return proxy\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export * from '@fictjs/runtime';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export { createMemo as $memo } from '@fictjs/runtime';
|
|
3
|
+
export { createScope, createSelector, runInScope } from '@fictjs/runtime/advanced';
|
|
4
|
+
|
|
5
|
+
declare function $store<T extends object>(initialValue: T): T;
|
|
6
|
+
|
|
7
|
+
export { $store };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export * from '@fictjs/runtime';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export { createMemo as $memo } from '@fictjs/runtime';
|
|
3
|
+
export { createScope, createSelector, runInScope } from '@fictjs/runtime/advanced';
|
|
4
|
+
|
|
5
|
+
declare function $store<T extends object>(initialValue: T): T;
|
|
6
|
+
|
|
7
|
+
export { $store };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export { $store } from './chunk-5AWNWCDT.js';
|
|
1
2
|
export * from '@fictjs/runtime';
|
|
3
|
+
export { createMemo as $memo } from '@fictjs/runtime';
|
|
4
|
+
export { createScope, createSelector, runInScope } from '@fictjs/runtime/advanced';
|
|
2
5
|
//# sourceMappingURL=index.js.map
|
|
3
6
|
//# sourceMappingURL=index.js.map
|
package/dist/plus.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var advanced = require('@fictjs/runtime/advanced');
|
|
3
4
|
var runtime = require('@fictjs/runtime');
|
|
4
5
|
|
|
5
6
|
// src/store.ts
|
|
@@ -15,7 +16,7 @@ function getSignal(target, prop) {
|
|
|
15
16
|
}
|
|
16
17
|
if (!signals[prop]) {
|
|
17
18
|
const initial = prop === ITERATE_KEY ? 0 : target[prop];
|
|
18
|
-
signals[prop] =
|
|
19
|
+
signals[prop] = advanced.createSignal(initial);
|
|
19
20
|
}
|
|
20
21
|
return signals[prop];
|
|
21
22
|
}
|
|
@@ -150,10 +151,10 @@ function resource(optionsOrFetcher) {
|
|
|
150
151
|
let state = cache.get(key);
|
|
151
152
|
if (!state) {
|
|
152
153
|
state = {
|
|
153
|
-
data:
|
|
154
|
-
loading:
|
|
155
|
-
error:
|
|
156
|
-
version:
|
|
154
|
+
data: advanced.createSignal(void 0),
|
|
155
|
+
loading: advanced.createSignal(false),
|
|
156
|
+
error: advanced.createSignal(void 0),
|
|
157
|
+
version: advanced.createSignal(0),
|
|
157
158
|
pendingToken: null,
|
|
158
159
|
lastArgs: void 0,
|
|
159
160
|
lastVersion: -1,
|
|
@@ -262,7 +263,7 @@ function resource(optionsOrFetcher) {
|
|
|
262
263
|
};
|
|
263
264
|
return {
|
|
264
265
|
read(argsAccessor) {
|
|
265
|
-
const entryRef =
|
|
266
|
+
const entryRef = advanced.createSignal(null);
|
|
266
267
|
runtime.createEffect(() => {
|
|
267
268
|
const key = computeKey(argsAccessor);
|
|
268
269
|
const entry = ensureEntry(key);
|
|
@@ -354,26 +355,6 @@ function lazy(loader) {
|
|
|
354
355
|
};
|
|
355
356
|
}
|
|
356
357
|
|
|
357
|
-
Object.defineProperty(exports, "startTransition", {
|
|
358
|
-
enumerable: true,
|
|
359
|
-
get: function () { return runtime.startTransition; }
|
|
360
|
-
});
|
|
361
|
-
Object.defineProperty(exports, "transition", {
|
|
362
|
-
enumerable: true,
|
|
363
|
-
get: function () { return runtime.startTransition; }
|
|
364
|
-
});
|
|
365
|
-
Object.defineProperty(exports, "untrack", {
|
|
366
|
-
enumerable: true,
|
|
367
|
-
get: function () { return runtime.untrack; }
|
|
368
|
-
});
|
|
369
|
-
Object.defineProperty(exports, "useDeferredValue", {
|
|
370
|
-
enumerable: true,
|
|
371
|
-
get: function () { return runtime.useDeferredValue; }
|
|
372
|
-
});
|
|
373
|
-
Object.defineProperty(exports, "useTransition", {
|
|
374
|
-
enumerable: true,
|
|
375
|
-
get: function () { return runtime.useTransition; }
|
|
376
|
-
});
|
|
377
358
|
exports.$store = $store;
|
|
378
359
|
exports.lazy = lazy;
|
|
379
360
|
exports.resource = resource;
|
package/dist/plus.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts","../src/resource.ts","../src/lazy.ts"],"names":["createSignal","signals","createSuspenseToken","onCleanup","entry","createEffect"],"mappings":"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","file":"plus.cjs","sourcesContent":["import { createSignal, type Signal } from '@fictjs/runtime'\n\ntype AnyFn = (...args: unknown[]) => unknown\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\nconst PROXY_CACHE = new WeakMap<object, unknown>()\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\nconst ITERATE_KEY = Symbol('iterate')\n\nfunction getSignal(target: object, prop: string | symbol): Signal<unknown> {\n let signals = SIGNAL_CACHE.get(target)\n if (!signals) {\n signals = {}\n SIGNAL_CACHE.set(target, signals)\n }\n if (!signals[prop]) {\n const initial = prop === ITERATE_KEY ? 0 : (target as Record<string | symbol, unknown>)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\nfunction triggerIteration(target: object) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[ITERATE_KEY]) {\n const current = signals[ITERATE_KEY]() as number\n signals[ITERATE_KEY](current + 1)\n }\n}\n\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n if (PROXY_CACHE.has(initialValue)) {\n return PROXY_CACHE.get(initialValue) as T\n }\n\n const proxy = new Proxy(initialValue, {\n get(target, prop, receiver) {\n // Always touch the signal so reference changes to this property are tracked,\n // even if the value is an object we proxy further.\n const signal = getSignal(target, prop)\n const trackedValue = signal()\n\n const currentValue = Reflect.get(target, prop, receiver ?? proxy)\n if (currentValue !== trackedValue) {\n // If the value has changed (e.g. via direct mutation of the underlying object not via proxy),\n // we update the signal to keep it in sync.\n // Note: This is a bit of a heuristic. Ideally all mutations go through proxy.\n signal(currentValue)\n }\n\n if (typeof currentValue === 'function') {\n let boundMethods = BOUND_METHOD_CACHE.get(target)\n if (!boundMethods) {\n boundMethods = new Map()\n BOUND_METHOD_CACHE.set(target, boundMethods)\n }\n const cached = boundMethods.get(prop)\n if (cached && cached.ref === currentValue) {\n return cached.bound\n }\n\n const bound = (currentValue as AnyFn).bind(receiver ?? proxy)\n boundMethods.set(prop, { ref: currentValue as AnyFn, bound })\n return bound\n }\n\n // If the value is an object/array, we recursively wrap it in a store\n if (typeof currentValue === 'object' && currentValue !== null) {\n return $store(currentValue as Record<string, unknown>)\n }\n\n // For primitives (and functions), we return the signal value (which tracks the read)\n return currentValue\n },\n\n set(target, prop, newValue, receiver) {\n const oldValue = Reflect.get(target, prop, receiver)\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n\n // If value hasn't changed, do nothing\n if (oldValue === newValue && hadKey) {\n return true\n }\n\n const result = Reflect.set(target, prop, newValue, receiver)\n\n // IMPORTANT: Clear bound method cache BEFORE updating the signal\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n // Update the signal if it exists\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](newValue)\n }\n\n // If new property, trigger iteration update\n if (!hadKey) {\n triggerIteration(target)\n }\n\n // Ensure array length subscribers are notified even if the native push/pop\n // doesn't trigger a separate set trap for \"length\" (defensive).\n if (Array.isArray(target) && prop !== 'length') {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals.length) {\n signals.length((target as unknown as { length: number }).length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n // But usually 'length' is set explicitly or handled by the runtime.\n if (Array.isArray(target) && prop === 'length') {\n triggerIteration(target)\n }\n\n return result\n },\n\n deleteProperty(target, prop) {\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n const result = Reflect.deleteProperty(target, prop)\n\n if (result && hadKey) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](undefined)\n }\n\n // Clear bound method cache\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n triggerIteration(target)\n }\n\n return result\n },\n\n ownKeys(target) {\n getSignal(target, ITERATE_KEY)()\n return Reflect.ownKeys(target)\n },\n\n has(target, prop) {\n getSignal(target, prop)()\n return Reflect.has(target, prop)\n },\n })\n\n PROXY_CACHE.set(initialValue, proxy)\n return proxy\n}\n","import { createSignal, createEffect, onCleanup, createSuspenseToken } from '@fictjs/runtime'\n\nexport interface ResourceResult<T> {\n data: T | undefined\n loading: boolean\n error: unknown\n refresh: () => void\n}\n\nexport interface ResourceCacheOptions {\n mode?: 'memory' | 'none'\n ttlMs?: number\n staleWhileRevalidate?: boolean\n cacheErrors?: boolean\n}\n\nexport interface ResourceOptions<T, Args> {\n key?: unknown\n fetch: (ctx: { signal: AbortSignal }, args: Args) => Promise<T>\n suspense?: boolean\n cache?: ResourceCacheOptions\n reset?: unknown | (() => unknown)\n}\n\ninterface ResourceEntry<T, Args> {\n data: ReturnType<typeof createSignal<T | undefined>>\n loading: ReturnType<typeof createSignal<boolean>>\n error: ReturnType<typeof createSignal<unknown>>\n version: ReturnType<typeof createSignal<number>>\n pendingToken: ReturnType<typeof createSuspenseToken> | null\n lastArgs: Args | undefined\n lastVersion: number\n lastReset: unknown\n hasValue: boolean\n status: 'idle' | 'pending' | 'success' | 'error'\n generation: number\n expiresAt: number | undefined\n inFlight: Promise<void> | undefined\n controller: AbortController | undefined\n}\n\nconst defaultCacheOptions: Required<ResourceCacheOptions> = {\n mode: 'memory',\n ttlMs: Number.POSITIVE_INFINITY,\n staleWhileRevalidate: false,\n cacheErrors: false,\n}\n\n/**\n * Creates a resource factory that can be read with arguments.\n *\n * @param optionsOrFetcher - Configuration object or fetcher function\n */\nexport function resource<T, Args = void>(\n optionsOrFetcher:\n | ((ctx: { signal: AbortSignal }, args: Args) => Promise<T>)\n | ResourceOptions<T, Args>,\n) {\n const fetcher = typeof optionsOrFetcher === 'function' ? optionsOrFetcher : optionsOrFetcher.fetch\n const useSuspense = typeof optionsOrFetcher === 'object' && !!optionsOrFetcher.suspense\n const cacheOptions: ResourceCacheOptions =\n typeof optionsOrFetcher === 'object' ? (optionsOrFetcher.cache ?? {}) : {}\n const resolvedCacheOptions = { ...defaultCacheOptions, ...cacheOptions }\n const cache = new Map<unknown, ResourceEntry<T, Args>>()\n\n const readArgs = (argsAccessor: (() => Args) | Args): Args =>\n typeof argsAccessor === 'function' ? (argsAccessor as () => Args)() : argsAccessor\n\n const computeKey = (argsAccessor: (() => Args) | Args): unknown => {\n const argsValue = readArgs(argsAccessor)\n if (typeof optionsOrFetcher === 'object' && optionsOrFetcher.key !== undefined) {\n const key = optionsOrFetcher.key\n return typeof key === 'function' ? (key as (args: Args) => unknown)(argsValue) : key\n }\n return argsValue\n }\n\n const readResetToken = (): unknown => {\n if (typeof optionsOrFetcher !== 'object') return undefined\n const reset = optionsOrFetcher.reset\n if (typeof reset === 'function' && (reset as () => unknown).length === 0) {\n return (reset as () => unknown)()\n }\n return reset\n }\n\n const ensureEntry = (key: unknown): ResourceEntry<T, Args> => {\n let state = cache.get(key)\n if (!state) {\n state = {\n data: createSignal<T | undefined>(undefined),\n loading: createSignal<boolean>(false),\n error: createSignal<unknown>(undefined),\n version: createSignal(0),\n pendingToken: null,\n lastArgs: undefined,\n lastVersion: -1,\n lastReset: undefined,\n hasValue: false,\n status: 'idle',\n generation: 0,\n expiresAt: undefined,\n inFlight: undefined,\n controller: undefined,\n }\n cache.set(key, state)\n }\n return state!\n }\n\n const isExpired = (entry: ResourceEntry<T, Args>): boolean => {\n if (resolvedCacheOptions.mode === 'none') return true\n if (!Number.isFinite(resolvedCacheOptions.ttlMs)) return false\n if (entry.expiresAt === undefined) return false\n return entry.expiresAt < Date.now()\n }\n\n const markExpiry = (entry: ResourceEntry<T, Args>) => {\n if (resolvedCacheOptions.mode === 'none') {\n entry.expiresAt = Date.now() - 1\n return\n }\n entry.expiresAt = Number.isFinite(resolvedCacheOptions.ttlMs)\n ? Date.now() + resolvedCacheOptions.ttlMs\n : undefined\n }\n\n const startFetch = (entry: ResourceEntry<T, Args>, key: unknown, args: Args) => {\n entry.controller?.abort()\n entry.inFlight = undefined\n const controller = new AbortController()\n entry.controller = controller\n entry.status = 'pending'\n entry.loading(true)\n entry.error(undefined)\n entry.generation += 1\n const currentGen = entry.generation\n\n const shouldSuspend = useSuspense && !entry.hasValue\n entry.pendingToken = shouldSuspend ? createSuspenseToken() : null\n\n const fetchPromise = fetcher({ signal: controller.signal }, args)\n .then(res => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.data(res)\n entry.hasValue = true\n entry.status = 'success'\n entry.loading(false)\n markExpiry(entry)\n if (entry.pendingToken) {\n entry.pendingToken.resolve()\n entry.pendingToken = null\n }\n })\n .catch(err => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.error(err)\n entry.status = 'error'\n entry.loading(false)\n if (resolvedCacheOptions.cacheErrors) {\n markExpiry(entry)\n } else {\n entry.expiresAt = Date.now() - 1\n entry.hasValue = false\n }\n if (entry.pendingToken) {\n entry.pendingToken.reject(err)\n entry.pendingToken = null\n }\n })\n .finally(() => {\n entry.inFlight = undefined\n entry.controller = undefined\n })\n\n entry.inFlight = fetchPromise\n\n onCleanup(() => {\n if (resolvedCacheOptions.mode === 'none') {\n controller.abort()\n cache.delete(key)\n }\n })\n }\n\n const invalidate = (key?: unknown) => {\n if (key === undefined) {\n cache.forEach(entry => {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n })\n cache.clear()\n return\n }\n const entry = cache.get(key)\n if (entry) {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n cache.delete(key)\n }\n }\n\n const prefetch = (args: Args, keyOverride?: unknown) => {\n const key = keyOverride ?? computeKey(args)\n const entry = ensureEntry(key)\n const usableData = entry.hasValue && !isExpired(entry)\n if (!usableData) {\n entry.lastArgs = args\n entry.lastVersion = entry.version()\n startFetch(entry, key, args)\n }\n }\n\n return {\n read(argsAccessor: (() => Args) | Args): ResourceResult<T> {\n const entryRef = createSignal<ResourceEntry<T, Args> | null>(null)\n\n createEffect(() => {\n const key = computeKey(argsAccessor)\n const entry = ensureEntry(key)\n entryRef(entry)\n const args = readArgs(argsAccessor)\n const currentVersion = entry.version()\n const expired = isExpired(entry)\n const argsChanged = entry.lastArgs !== args\n const versionChanged = entry.lastVersion !== currentVersion\n const resetToken = readResetToken()\n const resetChanged = entry.lastReset !== resetToken\n const shouldRefetch =\n expired ||\n argsChanged ||\n versionChanged ||\n resetChanged ||\n (entry.status === 'error' && !resolvedCacheOptions.cacheErrors)\n\n entry.lastArgs = args\n entry.lastVersion = currentVersion\n entry.lastReset = resetToken\n\n if (shouldRefetch) {\n if (entry.inFlight && (argsChanged || versionChanged)) {\n entry.controller?.abort()\n entry.inFlight = undefined\n }\n if (resetChanged) {\n entry.hasValue = false\n entry.expiresAt = Date.now() - 1\n }\n startFetch(entry, key, args as Args)\n } else if (\n entry.inFlight === undefined &&\n resolvedCacheOptions.staleWhileRevalidate &&\n expired &&\n entry.hasValue\n ) {\n // stale-while-revalidate: return stale data but refresh.\n startFetch(entry, key, args as Args)\n }\n\n if (resolvedCacheOptions.staleWhileRevalidate && entry.hasValue && expired) {\n entry.loading(true)\n }\n })\n\n return {\n get data() {\n const entry = entryRef()\n if (!entry) return undefined\n if (useSuspense && entry.pendingToken) {\n throw entry.pendingToken.token\n }\n return entry.data()\n },\n get loading() {\n const entry = entryRef()\n return entry ? entry.loading() : false\n },\n get error() {\n const entry = entryRef()\n return entry ? entry.error() : undefined\n },\n refresh: () => {\n const entry = entryRef()\n if (entry) entry.version(entry.version() + 1)\n },\n }\n },\n invalidate,\n prefetch,\n }\n}\n","import { createSuspenseToken } from '@fictjs/runtime'\nimport type { Component } from '@fictjs/runtime'\n\nexport interface LazyModule<TProps extends Record<string, unknown>> {\n default: Component<TProps>\n}\n\n/**\n * Create a lazy component that suspends while loading.\n */\nexport function lazy<TProps extends Record<string, unknown> = Record<string, unknown>>(\n loader: () => Promise<LazyModule<TProps> | { default: Component<TProps> }>,\n): Component<TProps> {\n let loaded: Component<TProps> | null = null\n let loadError: unknown = null\n let loadingPromise: Promise<unknown> | null = null\n let pendingToken: ReturnType<typeof createSuspenseToken> | null = null\n\n return props => {\n if (loaded) {\n return loaded(props)\n }\n if (loadError) {\n throw loadError\n }\n if (!loadingPromise) {\n pendingToken = createSuspenseToken()\n loadingPromise = loader()\n .then(mod => {\n loaded = (mod as LazyModule<TProps>).default\n pendingToken?.resolve()\n })\n .catch(err => {\n loadError = err\n pendingToken?.reject(err)\n })\n .finally(() => {\n loadingPromise = null\n pendingToken = null\n })\n }\n if (pendingToken) {\n throw pendingToken.token\n }\n // Should never hit if pendingToken exists, but fallback for type safety.\n throw new Error('Lazy component failed to start loading')\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store.ts","../src/resource.ts","../src/lazy.ts"],"names":["createSignal","signals","createSuspenseToken","onCleanup","entry","createEffect"],"mappings":"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","file":"plus.cjs","sourcesContent":["import { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\ntype AnyFn = (...args: unknown[]) => unknown\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\nconst PROXY_CACHE = new WeakMap<object, unknown>()\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\nconst ITERATE_KEY = Symbol('iterate')\n\nfunction getSignal(target: object, prop: string | symbol): Signal<unknown> {\n let signals = SIGNAL_CACHE.get(target)\n if (!signals) {\n signals = {}\n SIGNAL_CACHE.set(target, signals)\n }\n if (!signals[prop]) {\n const initial = prop === ITERATE_KEY ? 0 : (target as Record<string | symbol, unknown>)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\nfunction triggerIteration(target: object) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[ITERATE_KEY]) {\n const current = signals[ITERATE_KEY]() as number\n signals[ITERATE_KEY](current + 1)\n }\n}\n\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n if (PROXY_CACHE.has(initialValue)) {\n return PROXY_CACHE.get(initialValue) as T\n }\n\n const proxy = new Proxy(initialValue, {\n get(target, prop, receiver) {\n // Always touch the signal so reference changes to this property are tracked,\n // even if the value is an object we proxy further.\n const signal = getSignal(target, prop)\n const trackedValue = signal()\n\n const currentValue = Reflect.get(target, prop, receiver ?? proxy)\n if (currentValue !== trackedValue) {\n // If the value has changed (e.g. via direct mutation of the underlying object not via proxy),\n // we update the signal to keep it in sync.\n // Note: This is a bit of a heuristic. Ideally all mutations go through proxy.\n signal(currentValue)\n }\n\n if (typeof currentValue === 'function') {\n let boundMethods = BOUND_METHOD_CACHE.get(target)\n if (!boundMethods) {\n boundMethods = new Map()\n BOUND_METHOD_CACHE.set(target, boundMethods)\n }\n const cached = boundMethods.get(prop)\n if (cached && cached.ref === currentValue) {\n return cached.bound\n }\n\n const bound = (currentValue as AnyFn).bind(receiver ?? proxy)\n boundMethods.set(prop, { ref: currentValue as AnyFn, bound })\n return bound\n }\n\n // If the value is an object/array, we recursively wrap it in a store\n if (typeof currentValue === 'object' && currentValue !== null) {\n return $store(currentValue as Record<string, unknown>)\n }\n\n // For primitives (and functions), we return the signal value (which tracks the read)\n return currentValue\n },\n\n set(target, prop, newValue, receiver) {\n const oldValue = Reflect.get(target, prop, receiver)\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n\n // If value hasn't changed, do nothing\n if (oldValue === newValue && hadKey) {\n return true\n }\n\n const result = Reflect.set(target, prop, newValue, receiver)\n\n // IMPORTANT: Clear bound method cache BEFORE updating the signal\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n // Update the signal if it exists\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](newValue)\n }\n\n // If new property, trigger iteration update\n if (!hadKey) {\n triggerIteration(target)\n }\n\n // Ensure array length subscribers are notified even if the native push/pop\n // doesn't trigger a separate set trap for \"length\" (defensive).\n if (Array.isArray(target) && prop !== 'length') {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals.length) {\n signals.length((target as unknown as { length: number }).length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n // But usually 'length' is set explicitly or handled by the runtime.\n if (Array.isArray(target) && prop === 'length') {\n triggerIteration(target)\n }\n\n return result\n },\n\n deleteProperty(target, prop) {\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n const result = Reflect.deleteProperty(target, prop)\n\n if (result && hadKey) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](undefined)\n }\n\n // Clear bound method cache\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n triggerIteration(target)\n }\n\n return result\n },\n\n ownKeys(target) {\n getSignal(target, ITERATE_KEY)()\n return Reflect.ownKeys(target)\n },\n\n has(target, prop) {\n getSignal(target, prop)()\n return Reflect.has(target, prop)\n },\n })\n\n PROXY_CACHE.set(initialValue, proxy)\n return proxy\n}\n","import { createEffect, onCleanup, createSuspenseToken } from '@fictjs/runtime'\nimport { createSignal } from '@fictjs/runtime/advanced'\n\nexport interface ResourceResult<T> {\n data: T | undefined\n loading: boolean\n error: unknown\n refresh: () => void\n}\n\nexport interface ResourceCacheOptions {\n mode?: 'memory' | 'none'\n ttlMs?: number\n staleWhileRevalidate?: boolean\n cacheErrors?: boolean\n}\n\nexport interface ResourceOptions<T, Args> {\n key?: unknown\n fetch: (ctx: { signal: AbortSignal }, args: Args) => Promise<T>\n suspense?: boolean\n cache?: ResourceCacheOptions\n reset?: unknown | (() => unknown)\n}\n\ninterface ResourceEntry<T, Args> {\n data: ReturnType<typeof createSignal<T | undefined>>\n loading: ReturnType<typeof createSignal<boolean>>\n error: ReturnType<typeof createSignal<unknown>>\n version: ReturnType<typeof createSignal<number>>\n pendingToken: ReturnType<typeof createSuspenseToken> | null\n lastArgs: Args | undefined\n lastVersion: number\n lastReset: unknown\n hasValue: boolean\n status: 'idle' | 'pending' | 'success' | 'error'\n generation: number\n expiresAt: number | undefined\n inFlight: Promise<void> | undefined\n controller: AbortController | undefined\n}\n\nconst defaultCacheOptions: Required<ResourceCacheOptions> = {\n mode: 'memory',\n ttlMs: Number.POSITIVE_INFINITY,\n staleWhileRevalidate: false,\n cacheErrors: false,\n}\n\n/**\n * Creates a resource factory that can be read with arguments.\n *\n * @param optionsOrFetcher - Configuration object or fetcher function\n */\nexport function resource<T, Args = void>(\n optionsOrFetcher:\n | ((ctx: { signal: AbortSignal }, args: Args) => Promise<T>)\n | ResourceOptions<T, Args>,\n) {\n const fetcher = typeof optionsOrFetcher === 'function' ? optionsOrFetcher : optionsOrFetcher.fetch\n const useSuspense = typeof optionsOrFetcher === 'object' && !!optionsOrFetcher.suspense\n const cacheOptions: ResourceCacheOptions =\n typeof optionsOrFetcher === 'object' ? (optionsOrFetcher.cache ?? {}) : {}\n const resolvedCacheOptions = { ...defaultCacheOptions, ...cacheOptions }\n const cache = new Map<unknown, ResourceEntry<T, Args>>()\n\n const readArgs = (argsAccessor: (() => Args) | Args): Args =>\n typeof argsAccessor === 'function' ? (argsAccessor as () => Args)() : argsAccessor\n\n const computeKey = (argsAccessor: (() => Args) | Args): unknown => {\n const argsValue = readArgs(argsAccessor)\n if (typeof optionsOrFetcher === 'object' && optionsOrFetcher.key !== undefined) {\n const key = optionsOrFetcher.key\n return typeof key === 'function' ? (key as (args: Args) => unknown)(argsValue) : key\n }\n return argsValue\n }\n\n const readResetToken = (): unknown => {\n if (typeof optionsOrFetcher !== 'object') return undefined\n const reset = optionsOrFetcher.reset\n if (typeof reset === 'function' && (reset as () => unknown).length === 0) {\n return (reset as () => unknown)()\n }\n return reset\n }\n\n const ensureEntry = (key: unknown): ResourceEntry<T, Args> => {\n let state = cache.get(key)\n if (!state) {\n state = {\n data: createSignal<T | undefined>(undefined),\n loading: createSignal<boolean>(false),\n error: createSignal<unknown>(undefined),\n version: createSignal(0),\n pendingToken: null,\n lastArgs: undefined,\n lastVersion: -1,\n lastReset: undefined,\n hasValue: false,\n status: 'idle',\n generation: 0,\n expiresAt: undefined,\n inFlight: undefined,\n controller: undefined,\n }\n cache.set(key, state)\n }\n return state!\n }\n\n const isExpired = (entry: ResourceEntry<T, Args>): boolean => {\n if (resolvedCacheOptions.mode === 'none') return true\n if (!Number.isFinite(resolvedCacheOptions.ttlMs)) return false\n if (entry.expiresAt === undefined) return false\n return entry.expiresAt < Date.now()\n }\n\n const markExpiry = (entry: ResourceEntry<T, Args>) => {\n if (resolvedCacheOptions.mode === 'none') {\n entry.expiresAt = Date.now() - 1\n return\n }\n entry.expiresAt = Number.isFinite(resolvedCacheOptions.ttlMs)\n ? Date.now() + resolvedCacheOptions.ttlMs\n : undefined\n }\n\n const startFetch = (entry: ResourceEntry<T, Args>, key: unknown, args: Args) => {\n entry.controller?.abort()\n entry.inFlight = undefined\n const controller = new AbortController()\n entry.controller = controller\n entry.status = 'pending'\n entry.loading(true)\n entry.error(undefined)\n entry.generation += 1\n const currentGen = entry.generation\n\n const shouldSuspend = useSuspense && !entry.hasValue\n entry.pendingToken = shouldSuspend ? createSuspenseToken() : null\n\n const fetchPromise = fetcher({ signal: controller.signal }, args)\n .then(res => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.data(res)\n entry.hasValue = true\n entry.status = 'success'\n entry.loading(false)\n markExpiry(entry)\n if (entry.pendingToken) {\n entry.pendingToken.resolve()\n entry.pendingToken = null\n }\n })\n .catch(err => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.error(err)\n entry.status = 'error'\n entry.loading(false)\n if (resolvedCacheOptions.cacheErrors) {\n markExpiry(entry)\n } else {\n entry.expiresAt = Date.now() - 1\n entry.hasValue = false\n }\n if (entry.pendingToken) {\n entry.pendingToken.reject(err)\n entry.pendingToken = null\n }\n })\n .finally(() => {\n entry.inFlight = undefined\n entry.controller = undefined\n })\n\n entry.inFlight = fetchPromise\n\n onCleanup(() => {\n if (resolvedCacheOptions.mode === 'none') {\n controller.abort()\n cache.delete(key)\n }\n })\n }\n\n const invalidate = (key?: unknown) => {\n if (key === undefined) {\n cache.forEach(entry => {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n })\n cache.clear()\n return\n }\n const entry = cache.get(key)\n if (entry) {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n cache.delete(key)\n }\n }\n\n const prefetch = (args: Args, keyOverride?: unknown) => {\n const key = keyOverride ?? computeKey(args)\n const entry = ensureEntry(key)\n const usableData = entry.hasValue && !isExpired(entry)\n if (!usableData) {\n entry.lastArgs = args\n entry.lastVersion = entry.version()\n startFetch(entry, key, args)\n }\n }\n\n return {\n read(argsAccessor: (() => Args) | Args): ResourceResult<T> {\n const entryRef = createSignal<ResourceEntry<T, Args> | null>(null)\n\n createEffect(() => {\n const key = computeKey(argsAccessor)\n const entry = ensureEntry(key)\n entryRef(entry)\n const args = readArgs(argsAccessor)\n const currentVersion = entry.version()\n const expired = isExpired(entry)\n const argsChanged = entry.lastArgs !== args\n const versionChanged = entry.lastVersion !== currentVersion\n const resetToken = readResetToken()\n const resetChanged = entry.lastReset !== resetToken\n const shouldRefetch =\n expired ||\n argsChanged ||\n versionChanged ||\n resetChanged ||\n (entry.status === 'error' && !resolvedCacheOptions.cacheErrors)\n\n entry.lastArgs = args\n entry.lastVersion = currentVersion\n entry.lastReset = resetToken\n\n if (shouldRefetch) {\n if (entry.inFlight && (argsChanged || versionChanged)) {\n entry.controller?.abort()\n entry.inFlight = undefined\n }\n if (resetChanged) {\n entry.hasValue = false\n entry.expiresAt = Date.now() - 1\n }\n startFetch(entry, key, args as Args)\n } else if (\n entry.inFlight === undefined &&\n resolvedCacheOptions.staleWhileRevalidate &&\n expired &&\n entry.hasValue\n ) {\n // stale-while-revalidate: return stale data but refresh.\n startFetch(entry, key, args as Args)\n }\n\n if (resolvedCacheOptions.staleWhileRevalidate && entry.hasValue && expired) {\n entry.loading(true)\n }\n })\n\n return {\n get data() {\n const entry = entryRef()\n if (!entry) return undefined\n if (useSuspense && entry.pendingToken) {\n throw entry.pendingToken.token\n }\n return entry.data()\n },\n get loading() {\n const entry = entryRef()\n return entry ? entry.loading() : false\n },\n get error() {\n const entry = entryRef()\n return entry ? entry.error() : undefined\n },\n refresh: () => {\n const entry = entryRef()\n if (entry) entry.version(entry.version() + 1)\n },\n }\n },\n invalidate,\n prefetch,\n }\n}\n","import { createSuspenseToken } from '@fictjs/runtime'\nimport type { Component } from '@fictjs/runtime'\n\nexport interface LazyModule<TProps extends Record<string, unknown>> {\n default: Component<TProps>\n}\n\n/**\n * Create a lazy component that suspends while loading.\n */\nexport function lazy<TProps extends Record<string, unknown> = Record<string, unknown>>(\n loader: () => Promise<LazyModule<TProps> | { default: Component<TProps> }>,\n): Component<TProps> {\n let loaded: Component<TProps> | null = null\n let loadError: unknown = null\n let loadingPromise: Promise<unknown> | null = null\n let pendingToken: ReturnType<typeof createSuspenseToken> | null = null\n\n return props => {\n if (loaded) {\n return loaded(props)\n }\n if (loadError) {\n throw loadError\n }\n if (!loadingPromise) {\n pendingToken = createSuspenseToken()\n loadingPromise = loader()\n .then(mod => {\n loaded = (mod as LazyModule<TProps>).default\n pendingToken?.resolve()\n })\n .catch(err => {\n loadError = err\n pendingToken?.reject(err)\n })\n .finally(() => {\n loadingPromise = null\n pendingToken = null\n })\n }\n if (pendingToken) {\n throw pendingToken.token\n }\n // Should never hit if pendingToken exists, but fallback for type safety.\n throw new Error('Lazy component failed to start loading')\n }\n}\n"]}
|
package/dist/plus.d.cts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
export { $store } from './index.cjs';
|
|
1
2
|
import { Component } from '@fictjs/runtime';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare function $store<T extends object>(initialValue: T): T;
|
|
3
|
+
import '@fictjs/runtime/advanced';
|
|
5
4
|
|
|
6
5
|
interface ResourceResult<T> {
|
|
7
6
|
data: T | undefined;
|
|
@@ -47,4 +46,4 @@ declare function lazy<TProps extends Record<string, unknown> = Record<string, un
|
|
|
47
46
|
default: Component<TProps>;
|
|
48
47
|
}>): Component<TProps>;
|
|
49
48
|
|
|
50
|
-
export {
|
|
49
|
+
export { type LazyModule, type ResourceCacheOptions, type ResourceOptions, type ResourceResult, lazy, resource };
|
package/dist/plus.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
export { $store } from './index.js';
|
|
1
2
|
import { Component } from '@fictjs/runtime';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare function $store<T extends object>(initialValue: T): T;
|
|
3
|
+
import '@fictjs/runtime/advanced';
|
|
5
4
|
|
|
6
5
|
interface ResourceResult<T> {
|
|
7
6
|
data: T | undefined;
|
|
@@ -47,4 +46,4 @@ declare function lazy<TProps extends Record<string, unknown> = Record<string, un
|
|
|
47
46
|
default: Component<TProps>;
|
|
48
47
|
}>): Component<TProps>;
|
|
49
48
|
|
|
50
|
-
export {
|
|
49
|
+
export { type LazyModule, type ResourceCacheOptions, type ResourceOptions, type ResourceResult, lazy, resource };
|
package/dist/plus.js
CHANGED
|
@@ -1,121 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export { $store } from './chunk-5AWNWCDT.js';
|
|
2
|
+
import { createEffect, createSuspenseToken, onCleanup } from '@fictjs/runtime';
|
|
3
|
+
import { createSignal } from '@fictjs/runtime/advanced';
|
|
3
4
|
|
|
4
|
-
// src/store.ts
|
|
5
|
-
var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
|
|
6
|
-
var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
|
|
7
|
-
var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
|
|
8
|
-
var ITERATE_KEY = Symbol("iterate");
|
|
9
|
-
function getSignal(target, prop) {
|
|
10
|
-
let signals = SIGNAL_CACHE.get(target);
|
|
11
|
-
if (!signals) {
|
|
12
|
-
signals = {};
|
|
13
|
-
SIGNAL_CACHE.set(target, signals);
|
|
14
|
-
}
|
|
15
|
-
if (!signals[prop]) {
|
|
16
|
-
const initial = prop === ITERATE_KEY ? 0 : target[prop];
|
|
17
|
-
signals[prop] = createSignal(initial);
|
|
18
|
-
}
|
|
19
|
-
return signals[prop];
|
|
20
|
-
}
|
|
21
|
-
function triggerIteration(target) {
|
|
22
|
-
const signals = SIGNAL_CACHE.get(target);
|
|
23
|
-
if (signals && signals[ITERATE_KEY]) {
|
|
24
|
-
const current = signals[ITERATE_KEY]();
|
|
25
|
-
signals[ITERATE_KEY](current + 1);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function $store(initialValue) {
|
|
29
|
-
if (typeof initialValue !== "object" || initialValue === null) {
|
|
30
|
-
return initialValue;
|
|
31
|
-
}
|
|
32
|
-
if (PROXY_CACHE.has(initialValue)) {
|
|
33
|
-
return PROXY_CACHE.get(initialValue);
|
|
34
|
-
}
|
|
35
|
-
const proxy = new Proxy(initialValue, {
|
|
36
|
-
get(target, prop, receiver) {
|
|
37
|
-
const signal = getSignal(target, prop);
|
|
38
|
-
const trackedValue = signal();
|
|
39
|
-
const currentValue = Reflect.get(target, prop, receiver ?? proxy);
|
|
40
|
-
if (currentValue !== trackedValue) {
|
|
41
|
-
signal(currentValue);
|
|
42
|
-
}
|
|
43
|
-
if (typeof currentValue === "function") {
|
|
44
|
-
let boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
45
|
-
if (!boundMethods) {
|
|
46
|
-
boundMethods = /* @__PURE__ */ new Map();
|
|
47
|
-
BOUND_METHOD_CACHE.set(target, boundMethods);
|
|
48
|
-
}
|
|
49
|
-
const cached = boundMethods.get(prop);
|
|
50
|
-
if (cached && cached.ref === currentValue) {
|
|
51
|
-
return cached.bound;
|
|
52
|
-
}
|
|
53
|
-
const bound = currentValue.bind(receiver ?? proxy);
|
|
54
|
-
boundMethods.set(prop, { ref: currentValue, bound });
|
|
55
|
-
return bound;
|
|
56
|
-
}
|
|
57
|
-
if (typeof currentValue === "object" && currentValue !== null) {
|
|
58
|
-
return $store(currentValue);
|
|
59
|
-
}
|
|
60
|
-
return currentValue;
|
|
61
|
-
},
|
|
62
|
-
set(target, prop, newValue, receiver) {
|
|
63
|
-
const oldValue = Reflect.get(target, prop, receiver);
|
|
64
|
-
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
65
|
-
if (oldValue === newValue && hadKey) {
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
const result = Reflect.set(target, prop, newValue, receiver);
|
|
69
|
-
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
70
|
-
if (boundMethods && boundMethods.has(prop)) {
|
|
71
|
-
boundMethods.delete(prop);
|
|
72
|
-
}
|
|
73
|
-
const signals = SIGNAL_CACHE.get(target);
|
|
74
|
-
if (signals && signals[prop]) {
|
|
75
|
-
signals[prop](newValue);
|
|
76
|
-
}
|
|
77
|
-
if (!hadKey) {
|
|
78
|
-
triggerIteration(target);
|
|
79
|
-
}
|
|
80
|
-
if (Array.isArray(target) && prop !== "length") {
|
|
81
|
-
const signals2 = SIGNAL_CACHE.get(target);
|
|
82
|
-
if (signals2 && signals2.length) {
|
|
83
|
-
signals2.length(target.length);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (Array.isArray(target) && prop === "length") {
|
|
87
|
-
triggerIteration(target);
|
|
88
|
-
}
|
|
89
|
-
return result;
|
|
90
|
-
},
|
|
91
|
-
deleteProperty(target, prop) {
|
|
92
|
-
const hadKey = Object.prototype.hasOwnProperty.call(target, prop);
|
|
93
|
-
const result = Reflect.deleteProperty(target, prop);
|
|
94
|
-
if (result && hadKey) {
|
|
95
|
-
const signals = SIGNAL_CACHE.get(target);
|
|
96
|
-
if (signals && signals[prop]) {
|
|
97
|
-
signals[prop](void 0);
|
|
98
|
-
}
|
|
99
|
-
const boundMethods = BOUND_METHOD_CACHE.get(target);
|
|
100
|
-
if (boundMethods && boundMethods.has(prop)) {
|
|
101
|
-
boundMethods.delete(prop);
|
|
102
|
-
}
|
|
103
|
-
triggerIteration(target);
|
|
104
|
-
}
|
|
105
|
-
return result;
|
|
106
|
-
},
|
|
107
|
-
ownKeys(target) {
|
|
108
|
-
getSignal(target, ITERATE_KEY)();
|
|
109
|
-
return Reflect.ownKeys(target);
|
|
110
|
-
},
|
|
111
|
-
has(target, prop) {
|
|
112
|
-
getSignal(target, prop)();
|
|
113
|
-
return Reflect.has(target, prop);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
PROXY_CACHE.set(initialValue, proxy);
|
|
117
|
-
return proxy;
|
|
118
|
-
}
|
|
119
5
|
var defaultCacheOptions = {
|
|
120
6
|
mode: "memory",
|
|
121
7
|
ttlMs: Number.POSITIVE_INFINITY,
|
|
@@ -353,6 +239,6 @@ function lazy(loader) {
|
|
|
353
239
|
};
|
|
354
240
|
}
|
|
355
241
|
|
|
356
|
-
export {
|
|
242
|
+
export { lazy, resource };
|
|
357
243
|
//# sourceMappingURL=plus.js.map
|
|
358
244
|
//# sourceMappingURL=plus.js.map
|
package/dist/plus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts","../src/resource.ts","../src/lazy.ts"],"names":["signals","createSignal","entry","createSuspenseToken"],"mappings":"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","file":"plus.js","sourcesContent":["import { createSignal, type Signal } from '@fictjs/runtime'\n\ntype AnyFn = (...args: unknown[]) => unknown\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\nconst PROXY_CACHE = new WeakMap<object, unknown>()\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\nconst ITERATE_KEY = Symbol('iterate')\n\nfunction getSignal(target: object, prop: string | symbol): Signal<unknown> {\n let signals = SIGNAL_CACHE.get(target)\n if (!signals) {\n signals = {}\n SIGNAL_CACHE.set(target, signals)\n }\n if (!signals[prop]) {\n const initial = prop === ITERATE_KEY ? 0 : (target as Record<string | symbol, unknown>)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\nfunction triggerIteration(target: object) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[ITERATE_KEY]) {\n const current = signals[ITERATE_KEY]() as number\n signals[ITERATE_KEY](current + 1)\n }\n}\n\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n if (PROXY_CACHE.has(initialValue)) {\n return PROXY_CACHE.get(initialValue) as T\n }\n\n const proxy = new Proxy(initialValue, {\n get(target, prop, receiver) {\n // Always touch the signal so reference changes to this property are tracked,\n // even if the value is an object we proxy further.\n const signal = getSignal(target, prop)\n const trackedValue = signal()\n\n const currentValue = Reflect.get(target, prop, receiver ?? proxy)\n if (currentValue !== trackedValue) {\n // If the value has changed (e.g. via direct mutation of the underlying object not via proxy),\n // we update the signal to keep it in sync.\n // Note: This is a bit of a heuristic. Ideally all mutations go through proxy.\n signal(currentValue)\n }\n\n if (typeof currentValue === 'function') {\n let boundMethods = BOUND_METHOD_CACHE.get(target)\n if (!boundMethods) {\n boundMethods = new Map()\n BOUND_METHOD_CACHE.set(target, boundMethods)\n }\n const cached = boundMethods.get(prop)\n if (cached && cached.ref === currentValue) {\n return cached.bound\n }\n\n const bound = (currentValue as AnyFn).bind(receiver ?? proxy)\n boundMethods.set(prop, { ref: currentValue as AnyFn, bound })\n return bound\n }\n\n // If the value is an object/array, we recursively wrap it in a store\n if (typeof currentValue === 'object' && currentValue !== null) {\n return $store(currentValue as Record<string, unknown>)\n }\n\n // For primitives (and functions), we return the signal value (which tracks the read)\n return currentValue\n },\n\n set(target, prop, newValue, receiver) {\n const oldValue = Reflect.get(target, prop, receiver)\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n\n // If value hasn't changed, do nothing\n if (oldValue === newValue && hadKey) {\n return true\n }\n\n const result = Reflect.set(target, prop, newValue, receiver)\n\n // IMPORTANT: Clear bound method cache BEFORE updating the signal\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n // Update the signal if it exists\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](newValue)\n }\n\n // If new property, trigger iteration update\n if (!hadKey) {\n triggerIteration(target)\n }\n\n // Ensure array length subscribers are notified even if the native push/pop\n // doesn't trigger a separate set trap for \"length\" (defensive).\n if (Array.isArray(target) && prop !== 'length') {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals.length) {\n signals.length((target as unknown as { length: number }).length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n // But usually 'length' is set explicitly or handled by the runtime.\n if (Array.isArray(target) && prop === 'length') {\n triggerIteration(target)\n }\n\n return result\n },\n\n deleteProperty(target, prop) {\n const hadKey = Object.prototype.hasOwnProperty.call(target, prop)\n const result = Reflect.deleteProperty(target, prop)\n\n if (result && hadKey) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals && signals[prop]) {\n signals[prop](undefined)\n }\n\n // Clear bound method cache\n const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n }\n\n triggerIteration(target)\n }\n\n return result\n },\n\n ownKeys(target) {\n getSignal(target, ITERATE_KEY)()\n return Reflect.ownKeys(target)\n },\n\n has(target, prop) {\n getSignal(target, prop)()\n return Reflect.has(target, prop)\n },\n })\n\n PROXY_CACHE.set(initialValue, proxy)\n return proxy\n}\n","import { createSignal, createEffect, onCleanup, createSuspenseToken } from '@fictjs/runtime'\n\nexport interface ResourceResult<T> {\n data: T | undefined\n loading: boolean\n error: unknown\n refresh: () => void\n}\n\nexport interface ResourceCacheOptions {\n mode?: 'memory' | 'none'\n ttlMs?: number\n staleWhileRevalidate?: boolean\n cacheErrors?: boolean\n}\n\nexport interface ResourceOptions<T, Args> {\n key?: unknown\n fetch: (ctx: { signal: AbortSignal }, args: Args) => Promise<T>\n suspense?: boolean\n cache?: ResourceCacheOptions\n reset?: unknown | (() => unknown)\n}\n\ninterface ResourceEntry<T, Args> {\n data: ReturnType<typeof createSignal<T | undefined>>\n loading: ReturnType<typeof createSignal<boolean>>\n error: ReturnType<typeof createSignal<unknown>>\n version: ReturnType<typeof createSignal<number>>\n pendingToken: ReturnType<typeof createSuspenseToken> | null\n lastArgs: Args | undefined\n lastVersion: number\n lastReset: unknown\n hasValue: boolean\n status: 'idle' | 'pending' | 'success' | 'error'\n generation: number\n expiresAt: number | undefined\n inFlight: Promise<void> | undefined\n controller: AbortController | undefined\n}\n\nconst defaultCacheOptions: Required<ResourceCacheOptions> = {\n mode: 'memory',\n ttlMs: Number.POSITIVE_INFINITY,\n staleWhileRevalidate: false,\n cacheErrors: false,\n}\n\n/**\n * Creates a resource factory that can be read with arguments.\n *\n * @param optionsOrFetcher - Configuration object or fetcher function\n */\nexport function resource<T, Args = void>(\n optionsOrFetcher:\n | ((ctx: { signal: AbortSignal }, args: Args) => Promise<T>)\n | ResourceOptions<T, Args>,\n) {\n const fetcher = typeof optionsOrFetcher === 'function' ? optionsOrFetcher : optionsOrFetcher.fetch\n const useSuspense = typeof optionsOrFetcher === 'object' && !!optionsOrFetcher.suspense\n const cacheOptions: ResourceCacheOptions =\n typeof optionsOrFetcher === 'object' ? (optionsOrFetcher.cache ?? {}) : {}\n const resolvedCacheOptions = { ...defaultCacheOptions, ...cacheOptions }\n const cache = new Map<unknown, ResourceEntry<T, Args>>()\n\n const readArgs = (argsAccessor: (() => Args) | Args): Args =>\n typeof argsAccessor === 'function' ? (argsAccessor as () => Args)() : argsAccessor\n\n const computeKey = (argsAccessor: (() => Args) | Args): unknown => {\n const argsValue = readArgs(argsAccessor)\n if (typeof optionsOrFetcher === 'object' && optionsOrFetcher.key !== undefined) {\n const key = optionsOrFetcher.key\n return typeof key === 'function' ? (key as (args: Args) => unknown)(argsValue) : key\n }\n return argsValue\n }\n\n const readResetToken = (): unknown => {\n if (typeof optionsOrFetcher !== 'object') return undefined\n const reset = optionsOrFetcher.reset\n if (typeof reset === 'function' && (reset as () => unknown).length === 0) {\n return (reset as () => unknown)()\n }\n return reset\n }\n\n const ensureEntry = (key: unknown): ResourceEntry<T, Args> => {\n let state = cache.get(key)\n if (!state) {\n state = {\n data: createSignal<T | undefined>(undefined),\n loading: createSignal<boolean>(false),\n error: createSignal<unknown>(undefined),\n version: createSignal(0),\n pendingToken: null,\n lastArgs: undefined,\n lastVersion: -1,\n lastReset: undefined,\n hasValue: false,\n status: 'idle',\n generation: 0,\n expiresAt: undefined,\n inFlight: undefined,\n controller: undefined,\n }\n cache.set(key, state)\n }\n return state!\n }\n\n const isExpired = (entry: ResourceEntry<T, Args>): boolean => {\n if (resolvedCacheOptions.mode === 'none') return true\n if (!Number.isFinite(resolvedCacheOptions.ttlMs)) return false\n if (entry.expiresAt === undefined) return false\n return entry.expiresAt < Date.now()\n }\n\n const markExpiry = (entry: ResourceEntry<T, Args>) => {\n if (resolvedCacheOptions.mode === 'none') {\n entry.expiresAt = Date.now() - 1\n return\n }\n entry.expiresAt = Number.isFinite(resolvedCacheOptions.ttlMs)\n ? Date.now() + resolvedCacheOptions.ttlMs\n : undefined\n }\n\n const startFetch = (entry: ResourceEntry<T, Args>, key: unknown, args: Args) => {\n entry.controller?.abort()\n entry.inFlight = undefined\n const controller = new AbortController()\n entry.controller = controller\n entry.status = 'pending'\n entry.loading(true)\n entry.error(undefined)\n entry.generation += 1\n const currentGen = entry.generation\n\n const shouldSuspend = useSuspense && !entry.hasValue\n entry.pendingToken = shouldSuspend ? createSuspenseToken() : null\n\n const fetchPromise = fetcher({ signal: controller.signal }, args)\n .then(res => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.data(res)\n entry.hasValue = true\n entry.status = 'success'\n entry.loading(false)\n markExpiry(entry)\n if (entry.pendingToken) {\n entry.pendingToken.resolve()\n entry.pendingToken = null\n }\n })\n .catch(err => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.error(err)\n entry.status = 'error'\n entry.loading(false)\n if (resolvedCacheOptions.cacheErrors) {\n markExpiry(entry)\n } else {\n entry.expiresAt = Date.now() - 1\n entry.hasValue = false\n }\n if (entry.pendingToken) {\n entry.pendingToken.reject(err)\n entry.pendingToken = null\n }\n })\n .finally(() => {\n entry.inFlight = undefined\n entry.controller = undefined\n })\n\n entry.inFlight = fetchPromise\n\n onCleanup(() => {\n if (resolvedCacheOptions.mode === 'none') {\n controller.abort()\n cache.delete(key)\n }\n })\n }\n\n const invalidate = (key?: unknown) => {\n if (key === undefined) {\n cache.forEach(entry => {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n })\n cache.clear()\n return\n }\n const entry = cache.get(key)\n if (entry) {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n cache.delete(key)\n }\n }\n\n const prefetch = (args: Args, keyOverride?: unknown) => {\n const key = keyOverride ?? computeKey(args)\n const entry = ensureEntry(key)\n const usableData = entry.hasValue && !isExpired(entry)\n if (!usableData) {\n entry.lastArgs = args\n entry.lastVersion = entry.version()\n startFetch(entry, key, args)\n }\n }\n\n return {\n read(argsAccessor: (() => Args) | Args): ResourceResult<T> {\n const entryRef = createSignal<ResourceEntry<T, Args> | null>(null)\n\n createEffect(() => {\n const key = computeKey(argsAccessor)\n const entry = ensureEntry(key)\n entryRef(entry)\n const args = readArgs(argsAccessor)\n const currentVersion = entry.version()\n const expired = isExpired(entry)\n const argsChanged = entry.lastArgs !== args\n const versionChanged = entry.lastVersion !== currentVersion\n const resetToken = readResetToken()\n const resetChanged = entry.lastReset !== resetToken\n const shouldRefetch =\n expired ||\n argsChanged ||\n versionChanged ||\n resetChanged ||\n (entry.status === 'error' && !resolvedCacheOptions.cacheErrors)\n\n entry.lastArgs = args\n entry.lastVersion = currentVersion\n entry.lastReset = resetToken\n\n if (shouldRefetch) {\n if (entry.inFlight && (argsChanged || versionChanged)) {\n entry.controller?.abort()\n entry.inFlight = undefined\n }\n if (resetChanged) {\n entry.hasValue = false\n entry.expiresAt = Date.now() - 1\n }\n startFetch(entry, key, args as Args)\n } else if (\n entry.inFlight === undefined &&\n resolvedCacheOptions.staleWhileRevalidate &&\n expired &&\n entry.hasValue\n ) {\n // stale-while-revalidate: return stale data but refresh.\n startFetch(entry, key, args as Args)\n }\n\n if (resolvedCacheOptions.staleWhileRevalidate && entry.hasValue && expired) {\n entry.loading(true)\n }\n })\n\n return {\n get data() {\n const entry = entryRef()\n if (!entry) return undefined\n if (useSuspense && entry.pendingToken) {\n throw entry.pendingToken.token\n }\n return entry.data()\n },\n get loading() {\n const entry = entryRef()\n return entry ? entry.loading() : false\n },\n get error() {\n const entry = entryRef()\n return entry ? entry.error() : undefined\n },\n refresh: () => {\n const entry = entryRef()\n if (entry) entry.version(entry.version() + 1)\n },\n }\n },\n invalidate,\n prefetch,\n }\n}\n","import { createSuspenseToken } from '@fictjs/runtime'\nimport type { Component } from '@fictjs/runtime'\n\nexport interface LazyModule<TProps extends Record<string, unknown>> {\n default: Component<TProps>\n}\n\n/**\n * Create a lazy component that suspends while loading.\n */\nexport function lazy<TProps extends Record<string, unknown> = Record<string, unknown>>(\n loader: () => Promise<LazyModule<TProps> | { default: Component<TProps> }>,\n): Component<TProps> {\n let loaded: Component<TProps> | null = null\n let loadError: unknown = null\n let loadingPromise: Promise<unknown> | null = null\n let pendingToken: ReturnType<typeof createSuspenseToken> | null = null\n\n return props => {\n if (loaded) {\n return loaded(props)\n }\n if (loadError) {\n throw loadError\n }\n if (!loadingPromise) {\n pendingToken = createSuspenseToken()\n loadingPromise = loader()\n .then(mod => {\n loaded = (mod as LazyModule<TProps>).default\n pendingToken?.resolve()\n })\n .catch(err => {\n loadError = err\n pendingToken?.reject(err)\n })\n .finally(() => {\n loadingPromise = null\n pendingToken = null\n })\n }\n if (pendingToken) {\n throw pendingToken.token\n }\n // Should never hit if pendingToken exists, but fallback for type safety.\n throw new Error('Lazy component failed to start loading')\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/resource.ts","../src/lazy.ts"],"names":["entry","createSuspenseToken"],"mappings":"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","file":"plus.js","sourcesContent":["import { createEffect, onCleanup, createSuspenseToken } from '@fictjs/runtime'\nimport { createSignal } from '@fictjs/runtime/advanced'\n\nexport interface ResourceResult<T> {\n data: T | undefined\n loading: boolean\n error: unknown\n refresh: () => void\n}\n\nexport interface ResourceCacheOptions {\n mode?: 'memory' | 'none'\n ttlMs?: number\n staleWhileRevalidate?: boolean\n cacheErrors?: boolean\n}\n\nexport interface ResourceOptions<T, Args> {\n key?: unknown\n fetch: (ctx: { signal: AbortSignal }, args: Args) => Promise<T>\n suspense?: boolean\n cache?: ResourceCacheOptions\n reset?: unknown | (() => unknown)\n}\n\ninterface ResourceEntry<T, Args> {\n data: ReturnType<typeof createSignal<T | undefined>>\n loading: ReturnType<typeof createSignal<boolean>>\n error: ReturnType<typeof createSignal<unknown>>\n version: ReturnType<typeof createSignal<number>>\n pendingToken: ReturnType<typeof createSuspenseToken> | null\n lastArgs: Args | undefined\n lastVersion: number\n lastReset: unknown\n hasValue: boolean\n status: 'idle' | 'pending' | 'success' | 'error'\n generation: number\n expiresAt: number | undefined\n inFlight: Promise<void> | undefined\n controller: AbortController | undefined\n}\n\nconst defaultCacheOptions: Required<ResourceCacheOptions> = {\n mode: 'memory',\n ttlMs: Number.POSITIVE_INFINITY,\n staleWhileRevalidate: false,\n cacheErrors: false,\n}\n\n/**\n * Creates a resource factory that can be read with arguments.\n *\n * @param optionsOrFetcher - Configuration object or fetcher function\n */\nexport function resource<T, Args = void>(\n optionsOrFetcher:\n | ((ctx: { signal: AbortSignal }, args: Args) => Promise<T>)\n | ResourceOptions<T, Args>,\n) {\n const fetcher = typeof optionsOrFetcher === 'function' ? optionsOrFetcher : optionsOrFetcher.fetch\n const useSuspense = typeof optionsOrFetcher === 'object' && !!optionsOrFetcher.suspense\n const cacheOptions: ResourceCacheOptions =\n typeof optionsOrFetcher === 'object' ? (optionsOrFetcher.cache ?? {}) : {}\n const resolvedCacheOptions = { ...defaultCacheOptions, ...cacheOptions }\n const cache = new Map<unknown, ResourceEntry<T, Args>>()\n\n const readArgs = (argsAccessor: (() => Args) | Args): Args =>\n typeof argsAccessor === 'function' ? (argsAccessor as () => Args)() : argsAccessor\n\n const computeKey = (argsAccessor: (() => Args) | Args): unknown => {\n const argsValue = readArgs(argsAccessor)\n if (typeof optionsOrFetcher === 'object' && optionsOrFetcher.key !== undefined) {\n const key = optionsOrFetcher.key\n return typeof key === 'function' ? (key as (args: Args) => unknown)(argsValue) : key\n }\n return argsValue\n }\n\n const readResetToken = (): unknown => {\n if (typeof optionsOrFetcher !== 'object') return undefined\n const reset = optionsOrFetcher.reset\n if (typeof reset === 'function' && (reset as () => unknown).length === 0) {\n return (reset as () => unknown)()\n }\n return reset\n }\n\n const ensureEntry = (key: unknown): ResourceEntry<T, Args> => {\n let state = cache.get(key)\n if (!state) {\n state = {\n data: createSignal<T | undefined>(undefined),\n loading: createSignal<boolean>(false),\n error: createSignal<unknown>(undefined),\n version: createSignal(0),\n pendingToken: null,\n lastArgs: undefined,\n lastVersion: -1,\n lastReset: undefined,\n hasValue: false,\n status: 'idle',\n generation: 0,\n expiresAt: undefined,\n inFlight: undefined,\n controller: undefined,\n }\n cache.set(key, state)\n }\n return state!\n }\n\n const isExpired = (entry: ResourceEntry<T, Args>): boolean => {\n if (resolvedCacheOptions.mode === 'none') return true\n if (!Number.isFinite(resolvedCacheOptions.ttlMs)) return false\n if (entry.expiresAt === undefined) return false\n return entry.expiresAt < Date.now()\n }\n\n const markExpiry = (entry: ResourceEntry<T, Args>) => {\n if (resolvedCacheOptions.mode === 'none') {\n entry.expiresAt = Date.now() - 1\n return\n }\n entry.expiresAt = Number.isFinite(resolvedCacheOptions.ttlMs)\n ? Date.now() + resolvedCacheOptions.ttlMs\n : undefined\n }\n\n const startFetch = (entry: ResourceEntry<T, Args>, key: unknown, args: Args) => {\n entry.controller?.abort()\n entry.inFlight = undefined\n const controller = new AbortController()\n entry.controller = controller\n entry.status = 'pending'\n entry.loading(true)\n entry.error(undefined)\n entry.generation += 1\n const currentGen = entry.generation\n\n const shouldSuspend = useSuspense && !entry.hasValue\n entry.pendingToken = shouldSuspend ? createSuspenseToken() : null\n\n const fetchPromise = fetcher({ signal: controller.signal }, args)\n .then(res => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.data(res)\n entry.hasValue = true\n entry.status = 'success'\n entry.loading(false)\n markExpiry(entry)\n if (entry.pendingToken) {\n entry.pendingToken.resolve()\n entry.pendingToken = null\n }\n })\n .catch(err => {\n if (controller.signal.aborted || entry.generation !== currentGen) return\n entry.error(err)\n entry.status = 'error'\n entry.loading(false)\n if (resolvedCacheOptions.cacheErrors) {\n markExpiry(entry)\n } else {\n entry.expiresAt = Date.now() - 1\n entry.hasValue = false\n }\n if (entry.pendingToken) {\n entry.pendingToken.reject(err)\n entry.pendingToken = null\n }\n })\n .finally(() => {\n entry.inFlight = undefined\n entry.controller = undefined\n })\n\n entry.inFlight = fetchPromise\n\n onCleanup(() => {\n if (resolvedCacheOptions.mode === 'none') {\n controller.abort()\n cache.delete(key)\n }\n })\n }\n\n const invalidate = (key?: unknown) => {\n if (key === undefined) {\n cache.forEach(entry => {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n })\n cache.clear()\n return\n }\n const entry = cache.get(key)\n if (entry) {\n entry.controller?.abort()\n entry.version(entry.version() + 1)\n entry.expiresAt = Date.now() - 1\n cache.delete(key)\n }\n }\n\n const prefetch = (args: Args, keyOverride?: unknown) => {\n const key = keyOverride ?? computeKey(args)\n const entry = ensureEntry(key)\n const usableData = entry.hasValue && !isExpired(entry)\n if (!usableData) {\n entry.lastArgs = args\n entry.lastVersion = entry.version()\n startFetch(entry, key, args)\n }\n }\n\n return {\n read(argsAccessor: (() => Args) | Args): ResourceResult<T> {\n const entryRef = createSignal<ResourceEntry<T, Args> | null>(null)\n\n createEffect(() => {\n const key = computeKey(argsAccessor)\n const entry = ensureEntry(key)\n entryRef(entry)\n const args = readArgs(argsAccessor)\n const currentVersion = entry.version()\n const expired = isExpired(entry)\n const argsChanged = entry.lastArgs !== args\n const versionChanged = entry.lastVersion !== currentVersion\n const resetToken = readResetToken()\n const resetChanged = entry.lastReset !== resetToken\n const shouldRefetch =\n expired ||\n argsChanged ||\n versionChanged ||\n resetChanged ||\n (entry.status === 'error' && !resolvedCacheOptions.cacheErrors)\n\n entry.lastArgs = args\n entry.lastVersion = currentVersion\n entry.lastReset = resetToken\n\n if (shouldRefetch) {\n if (entry.inFlight && (argsChanged || versionChanged)) {\n entry.controller?.abort()\n entry.inFlight = undefined\n }\n if (resetChanged) {\n entry.hasValue = false\n entry.expiresAt = Date.now() - 1\n }\n startFetch(entry, key, args as Args)\n } else if (\n entry.inFlight === undefined &&\n resolvedCacheOptions.staleWhileRevalidate &&\n expired &&\n entry.hasValue\n ) {\n // stale-while-revalidate: return stale data but refresh.\n startFetch(entry, key, args as Args)\n }\n\n if (resolvedCacheOptions.staleWhileRevalidate && entry.hasValue && expired) {\n entry.loading(true)\n }\n })\n\n return {\n get data() {\n const entry = entryRef()\n if (!entry) return undefined\n if (useSuspense && entry.pendingToken) {\n throw entry.pendingToken.token\n }\n return entry.data()\n },\n get loading() {\n const entry = entryRef()\n return entry ? entry.loading() : false\n },\n get error() {\n const entry = entryRef()\n return entry ? entry.error() : undefined\n },\n refresh: () => {\n const entry = entryRef()\n if (entry) entry.version(entry.version() + 1)\n },\n }\n },\n invalidate,\n prefetch,\n }\n}\n","import { createSuspenseToken } from '@fictjs/runtime'\nimport type { Component } from '@fictjs/runtime'\n\nexport interface LazyModule<TProps extends Record<string, unknown>> {\n default: Component<TProps>\n}\n\n/**\n * Create a lazy component that suspends while loading.\n */\nexport function lazy<TProps extends Record<string, unknown> = Record<string, unknown>>(\n loader: () => Promise<LazyModule<TProps> | { default: Component<TProps> }>,\n): Component<TProps> {\n let loaded: Component<TProps> | null = null\n let loadError: unknown = null\n let loadingPromise: Promise<unknown> | null = null\n let pendingToken: ReturnType<typeof createSuspenseToken> | null = null\n\n return props => {\n if (loaded) {\n return loaded(props)\n }\n if (loadError) {\n throw loadError\n }\n if (!loadingPromise) {\n pendingToken = createSuspenseToken()\n loadingPromise = loader()\n .then(mod => {\n loaded = (mod as LazyModule<TProps>).default\n pendingToken?.resolve()\n })\n .catch(err => {\n loadError = err\n pendingToken?.reject(err)\n })\n .finally(() => {\n loadingPromise = null\n pendingToken = null\n })\n }\n if (pendingToken) {\n throw pendingToken.token\n }\n // Should never hit if pendingToken exists, but fallback for type safety.\n throw new Error('Lazy component failed to start loading')\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fict",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Main package for the Fict framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -43,6 +43,11 @@
|
|
|
43
43
|
"types": "./dist/plus.d.ts",
|
|
44
44
|
"import": "./dist/plus.js",
|
|
45
45
|
"require": "./dist/plus.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./advanced": {
|
|
48
|
+
"types": "./dist/advanced.d.ts",
|
|
49
|
+
"import": "./dist/advanced.js",
|
|
50
|
+
"require": "./dist/advanced.cjs"
|
|
46
51
|
}
|
|
47
52
|
},
|
|
48
53
|
"sideEffects": false,
|
|
@@ -51,12 +56,12 @@
|
|
|
51
56
|
"src"
|
|
52
57
|
],
|
|
53
58
|
"dependencies": {
|
|
54
|
-
"@fictjs/runtime": "0.0.
|
|
59
|
+
"@fictjs/runtime": "0.0.14"
|
|
55
60
|
},
|
|
56
61
|
"devDependencies": {
|
|
57
62
|
"tsup": "^8.5.1",
|
|
58
63
|
"vite": "^7.3.0",
|
|
59
|
-
"@fictjs/vite-plugin": "0.0.
|
|
64
|
+
"@fictjs/vite-plugin": "0.0.14"
|
|
60
65
|
},
|
|
61
66
|
"scripts": {
|
|
62
67
|
"build": "tsup",
|
package/src/advanced.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fict Advanced APIs
|
|
3
|
+
*
|
|
4
|
+
* This module exports advanced APIs for power users and library authors.
|
|
5
|
+
* These APIs require deeper understanding of Fict internals.
|
|
6
|
+
*
|
|
7
|
+
* @advanced
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Re-export all advanced APIs from runtime
|
|
12
|
+
export {
|
|
13
|
+
// Reactive Scope Management
|
|
14
|
+
createScope,
|
|
15
|
+
runInScope,
|
|
16
|
+
effectScope,
|
|
17
|
+
type ReactiveScope,
|
|
18
|
+
|
|
19
|
+
// Fine-grained Subscription
|
|
20
|
+
createSelector,
|
|
21
|
+
|
|
22
|
+
// Versioned Signal
|
|
23
|
+
createVersionedSignal,
|
|
24
|
+
type VersionedSignal,
|
|
25
|
+
type VersionedSignalOptions,
|
|
26
|
+
|
|
27
|
+
// High-Level Binding Factories
|
|
28
|
+
createTextBinding,
|
|
29
|
+
createChildBinding,
|
|
30
|
+
createAttributeBinding,
|
|
31
|
+
createStyleBinding,
|
|
32
|
+
createClassBinding,
|
|
33
|
+
createShow,
|
|
34
|
+
|
|
35
|
+
// Utilities
|
|
36
|
+
isReactive,
|
|
37
|
+
unwrap,
|
|
38
|
+
|
|
39
|
+
// Debugging & DevTools
|
|
40
|
+
getDevtoolsHook,
|
|
41
|
+
setCycleProtectionOptions,
|
|
42
|
+
type FictDevtoolsHook,
|
|
43
|
+
|
|
44
|
+
// Low-level Primitives
|
|
45
|
+
createRenderEffect,
|
|
46
|
+
|
|
47
|
+
// Context API (for subtree scoping / SSR isolation / multi-instance)
|
|
48
|
+
createContext,
|
|
49
|
+
useContext,
|
|
50
|
+
hasContext,
|
|
51
|
+
type Context,
|
|
52
|
+
type ProviderProps,
|
|
53
|
+
|
|
54
|
+
// Cross-component Signal (escape hatch for scalar/lightweight values)
|
|
55
|
+
createSignal,
|
|
56
|
+
type Signal,
|
|
57
|
+
} from '@fictjs/runtime/advanced'
|
package/src/index.ts
CHANGED
|
@@ -1 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fict Framework - Complete API
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for the Fict framework.
|
|
5
|
+
*
|
|
6
|
+
* ## Recommended Import Pattern (v1.0+)
|
|
7
|
+
*
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Core public API (most users need only this)
|
|
10
|
+
* // Use $state in components (compiler-transformed)
|
|
11
|
+
* // Use $store for cross-component shared state
|
|
12
|
+
* import { $store, render } from 'fict'
|
|
13
|
+
*
|
|
14
|
+
* // Async utilities
|
|
15
|
+
* import { resource, lazy } from 'fict/plus'
|
|
16
|
+
*
|
|
17
|
+
* // Advanced APIs (escape hatches, library authors)
|
|
18
|
+
* import { createSignal, createContext, createScope } from 'fict/advanced'
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ## State Management Guide
|
|
22
|
+
*
|
|
23
|
+
* | Use Case | API |
|
|
24
|
+
* |----------|-----|
|
|
25
|
+
* | Component-local state | `$state` (compiler-transformed) |
|
|
26
|
+
* | Derived values / side effects | JS + auto-derived + `$effect` |
|
|
27
|
+
* | Cross-component (large objects, deep mutation) | `$store` |
|
|
28
|
+
* | Cross-component (scalar/lightweight, library-level) | `createSignal` (advanced) |
|
|
29
|
+
* | Cross-component (subtree scope, SSR isolation) | `Context` (advanced) |
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
* @packageDocumentation
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// Re-export everything from runtime
|
|
1
36
|
export * from '@fictjs/runtime'
|
|
37
|
+
|
|
38
|
+
// Re-export commonly used advanced APIs for convenience
|
|
39
|
+
export { createSelector, createScope, runInScope } from '@fictjs/runtime/advanced'
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Convenience Aliases
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Alias for createMemo.
|
|
47
|
+
* Creates a memoized value that only recomputes when dependencies change.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```tsx
|
|
51
|
+
* const fullName = $memo(() => firstName + ' ' + lastName)
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export { createMemo as $memo } from '@fictjs/runtime'
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Deep Reactive Store (Proxy-based)
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a deep reactive store using Proxy.
|
|
64
|
+
* Unlike createStore, $store allows direct mutation.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* const user = $store({ name: 'Alice', address: { city: 'Beijing' } })
|
|
69
|
+
* user.name = 'Bob' // Reactive update
|
|
70
|
+
* user.address.city = 'Shanghai' // Deep reactive
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export { $store } from './store'
|
package/src/plus.ts
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fict Plus - Async Utilities and Store
|
|
3
|
+
*
|
|
4
|
+
* This module exports utilities for async data handling:
|
|
5
|
+
* - resource: Async data fetching with caching and Suspense support
|
|
6
|
+
* - lazy: Code-splitting with lazy component loading
|
|
7
|
+
* - $store: Re-exported for backward compatibility (prefer importing from 'fict')
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Store (re-exported for backward compatibility)
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
1
17
|
export { $store } from './store'
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Async Resource
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
2
23
|
export { resource } from './resource'
|
|
24
|
+
export type { ResourceResult, ResourceOptions, ResourceCacheOptions } from './resource'
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Lazy Loading
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
3
30
|
export { lazy } from './lazy'
|
|
4
|
-
export {
|
|
5
|
-
untrack,
|
|
6
|
-
startTransition,
|
|
7
|
-
useTransition,
|
|
8
|
-
useDeferredValue,
|
|
9
|
-
startTransition as transition,
|
|
10
|
-
} from '@fictjs/runtime'
|
|
31
|
+
export type { LazyModule } from './lazy'
|
package/src/resource.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createEffect, onCleanup, createSuspenseToken } from '@fictjs/runtime'
|
|
2
|
+
import { createSignal } from '@fictjs/runtime/advanced'
|
|
2
3
|
|
|
3
4
|
export interface ResourceResult<T> {
|
|
4
5
|
data: T | undefined
|
package/src/store.ts
CHANGED