fict 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,3 +30,11 @@ yarn add fict
30
30
  ```
31
31
 
32
32
  You can visit [Fict](https://github.com/fictjs/fict) for more documentation.
33
+
34
+ ## Package Surfaces
35
+
36
+ - `fict`: application-facing API and compiler macros (`$state`, `$effect`).
37
+ - `fict/plus`: async resource and lazy component helpers.
38
+ - `fict/advanced`: escape hatches for library authors and low-level reactive integration.
39
+ - `fict/loader`: SSR/resume loader entrypoint.
40
+ - `fict/internal`: compiler ABI for generated code only; do not import by hand.
package/dist/advanced.cjs CHANGED
@@ -4,6 +4,14 @@ var advanced = require('@fictjs/runtime/advanced');
4
4
 
5
5
 
6
6
 
7
+ Object.defineProperty(exports, "FICT_DEVTOOLS_MIN_PROTOCOL_VERSION", {
8
+ enumerable: true,
9
+ get: function () { return advanced.FICT_DEVTOOLS_MIN_PROTOCOL_VERSION; }
10
+ });
11
+ Object.defineProperty(exports, "FICT_DEVTOOLS_PROTOCOL_VERSION", {
12
+ enumerable: true,
13
+ get: function () { return advanced.FICT_DEVTOOLS_PROTOCOL_VERSION; }
14
+ });
7
15
  Object.defineProperty(exports, "createAttributeBinding", {
8
16
  enumerable: true,
9
17
  get: function () { return advanced.createAttributeBinding; }
@@ -64,10 +72,22 @@ Object.defineProperty(exports, "hasContext", {
64
72
  enumerable: true,
65
73
  get: function () { return advanced.hasContext; }
66
74
  });
75
+ Object.defineProperty(exports, "isDevtoolsHookCompatible", {
76
+ enumerable: true,
77
+ get: function () { return advanced.isDevtoolsHookCompatible; }
78
+ });
67
79
  Object.defineProperty(exports, "isReactive", {
68
80
  enumerable: true,
69
81
  get: function () { return advanced.isReactive; }
70
82
  });
83
+ Object.defineProperty(exports, "nonReactive", {
84
+ enumerable: true,
85
+ get: function () { return advanced.nonReactive; }
86
+ });
87
+ Object.defineProperty(exports, "reactive", {
88
+ enumerable: true,
89
+ get: function () { return advanced.reactive; }
90
+ });
71
91
  Object.defineProperty(exports, "runInScope", {
72
92
  enumerable: true,
73
93
  get: function () { return advanced.runInScope; }
@@ -1,4 +1,4 @@
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';
1
+ export { Context, FICT_DEVTOOLS_MIN_PROTOCOL_VERSION, FICT_DEVTOOLS_PROTOCOL_VERSION, FictDevtoolsCompatibility, FictDevtoolsHook, ProviderProps, ReactiveScope, Signal, VersionedSignal, VersionedSignalOptions, createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isDevtoolsHookCompatible, isReactive, nonReactive, reactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
2
2
  import '@fictjs/runtime/internal/list';
3
3
  import '@fictjs/runtime/internal';
4
4
  import '@fictjs/runtime/jsx-dev-runtime';
@@ -1,4 +1,4 @@
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';
1
+ export { Context, FICT_DEVTOOLS_MIN_PROTOCOL_VERSION, FICT_DEVTOOLS_PROTOCOL_VERSION, FictDevtoolsCompatibility, FictDevtoolsHook, ProviderProps, ReactiveScope, Signal, VersionedSignal, VersionedSignalOptions, createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isDevtoolsHookCompatible, isReactive, nonReactive, reactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
2
2
  import '@fictjs/runtime/internal/list';
3
3
  import '@fictjs/runtime/internal';
4
4
  import '@fictjs/runtime/jsx-dev-runtime';
package/dist/advanced.js CHANGED
@@ -1,3 +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';
1
+ export { FICT_DEVTOOLS_MIN_PROTOCOL_VERSION, FICT_DEVTOOLS_PROTOCOL_VERSION, createAttributeBinding, createChildBinding, createClassBinding, createContext, createRenderEffect, createScope, createSelector, createShow, createSignal, createStyleBinding, createTextBinding, createVersionedSignal, effectScope, getDevtoolsHook, hasContext, isDevtoolsHookCompatible, isReactive, nonReactive, reactive, runInScope, setCycleProtectionOptions, unwrap, useContext } from '@fictjs/runtime/advanced';
2
2
  //# sourceMappingURL=advanced.js.map
3
3
  //# sourceMappingURL=advanced.js.map
@@ -5,8 +5,8 @@ var IS_STORE_PROXY = Symbol("fict-store-proxy");
5
5
  var RAW_TO_PROXY = /* @__PURE__ */ new WeakMap();
6
6
  var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
7
7
  var isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
8
- var MUTATION_WARNED = /* @__PURE__ */ new WeakMap();
9
- var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
8
+ var MUTATION_WARNED = /* @__PURE__ */ new WeakSet();
9
+ var SKIP_MUTATION_WARNING_PROPS = [
10
10
  "constructor",
11
11
  "prototype",
12
12
  "__proto__",
@@ -19,7 +19,7 @@ var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
19
19
  Symbol.toStringTag,
20
20
  Symbol.iterator,
21
21
  Symbol.toPrimitive
22
- ]);
22
+ ];
23
23
  var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
24
24
  var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
25
25
  var ITERATE_KEY = Symbol("iterate");
@@ -63,18 +63,9 @@ function $store(initialValue) {
63
63
  const signal = getSignal(target, prop);
64
64
  const trackedValue = signal();
65
65
  const currentValue = Reflect.get(target, prop, receiver ?? proxy);
66
- if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.has(prop)) {
67
- let warnedProps = MUTATION_WARNED.get(target);
68
- if (!warnedProps) {
69
- warnedProps = /* @__PURE__ */ new Set();
70
- MUTATION_WARNED.set(target, warnedProps);
71
- }
72
- if (!warnedProps.has(prop)) {
73
- warnedProps.add(prop);
74
- console.warn(
75
- `[fict] Direct mutation detected for "${String(prop)}"; mutate via $store proxy.`
76
- );
77
- }
66
+ if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.includes(prop) && !MUTATION_WARNED.has(target)) {
67
+ MUTATION_WARNED.add(target);
68
+ console.warn(`[fict] Use $store for ${String(prop)}.`);
78
69
  }
79
70
  if (typeof currentValue === "function") {
80
71
  let boundMethods = BOUND_METHOD_CACHE.get(target);
@@ -127,20 +118,18 @@ function $store(initialValue) {
127
118
  triggerIteration(target);
128
119
  }
129
120
  if (Array.isArray(target) && prop !== "length") {
130
- const signals2 = SIGNAL_CACHE.get(target);
131
- if (signals2 && signals2.length) {
132
- signals2.length(target.length);
121
+ if (signals && signals.length) {
122
+ signals.length(target.length);
133
123
  }
134
124
  }
135
125
  if (Array.isArray(target) && prop === "length") {
136
126
  const nextLength = target.length;
137
127
  if (typeof oldLength === "number" && nextLength < oldLength) {
138
- const signals2 = SIGNAL_CACHE.get(target);
139
- if (signals2) {
128
+ if (signals) {
140
129
  for (let i = nextLength; i < oldLength; i += 1) {
141
130
  const key = String(i);
142
- if (signals2[key]) {
143
- signals2[key](void 0);
131
+ if (signals[key]) {
132
+ signals[key](void 0);
144
133
  }
145
134
  }
146
135
  }
@@ -183,5 +172,5 @@ function $store(initialValue) {
183
172
  }
184
173
 
185
174
  export { $store };
186
- //# sourceMappingURL=chunk-43IPAXWW.js.map
187
- //# sourceMappingURL=chunk-43IPAXWW.js.map
175
+ //# sourceMappingURL=chunk-7CM2UZ6M.js.map
176
+ //# sourceMappingURL=chunk-7CM2UZ6M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"chunk-7CM2UZ6M.js","sourcesContent":["/**\n * @fileoverview Deep reactive store implementation for Fict.\n *\n * $store creates a deeply reactive proxy that tracks property access at the path level.\n * Unlike $state (which is shallow), $store allows direct mutation of nested properties.\n *\n * @example\n * ```typescript\n * const user = $store({ name: 'Alice', address: { city: 'London' } })\n * user.address.city = 'Paris' // Fine-grained reactive update\n * ```\n */\n\nimport { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\n/** Function type for bound methods */\ntype AnyFn = (...args: unknown[]) => unknown\n\n/** Cache entry for bound methods to preserve identity */\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\n/** Type for objects with indexable properties */\ntype IndexableObject = Record<string | symbol, unknown>\n\n/** Symbol to mark proxies and prevent double-wrapping */\nconst IS_STORE_PROXY = Symbol('fict-store-proxy')\n\n/** WeakSet to track raw objects that have been proxied (for reverse lookup) */\nconst RAW_TO_PROXY = new WeakMap<object, object>()\n\n/** Cache of proxied objects to avoid duplicate proxies */\nconst PROXY_CACHE = new WeakMap<object, unknown>()\n\n/** Dev mode detection */\nconst isDev =\n typeof __DEV__ !== 'undefined'\n ? __DEV__\n : typeof process === 'undefined' || process.env?.NODE_ENV !== 'production'\n\n/** Track if we've warned about direct mutation for a target object */\nconst MUTATION_WARNED = new WeakSet<object>()\n\n/** Properties to skip for direct mutation warning (built-in/internal properties) */\nconst SKIP_MUTATION_WARNING_PROPS: (string | symbol)[] = [\n 'constructor',\n 'prototype',\n '__proto__',\n 'toString',\n 'valueOf',\n 'toLocaleString',\n 'hasOwnProperty',\n 'isPrototypeOf',\n 'propertyIsEnumerable',\n Symbol.toStringTag,\n Symbol.iterator,\n Symbol.toPrimitive,\n]\n\n/** Cache of signals per object property */\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\n\n/** Cache of bound methods to preserve function identity across reads */\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\n\n/** Special key for tracking iteration (Object.keys, for-in, etc.) */\nconst ITERATE_KEY = Symbol('iterate')\n\n/**\n * Get or create a signal for a specific property on a target object.\n * @internal\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 IndexableObject)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\n/**\n * Trigger iteration signal to notify consumers that keys have changed.\n * @internal\n */\nfunction triggerIteration(target: object): void {\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\n/**\n * Create a deep reactive store using Proxy.\n *\n * Unlike `$state` (which is shallow and compiler-transformed), `$store` provides:\n * - **Deep reactivity**: Nested objects are automatically wrapped in proxies\n * - **Direct mutation**: Modify properties directly without spread operators\n * - **Path-level tracking**: Only components reading changed paths re-render\n *\n * @param initialValue - The initial object to make reactive\n * @returns A reactive proxy of the object\n *\n * @example\n * ```tsx\n * import { $store } from 'fict'\n *\n * const form = $store({\n * user: { name: '', email: '' },\n * settings: { theme: 'light' }\n * })\n *\n * // Direct mutation works\n * form.user.name = 'Alice'\n *\n * // In JSX - only updates when form.user.name changes\n * <input value={form.user.name} />\n * ```\n *\n * @public\n */\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n // Prevent double-wrapping - if already a store proxy, return as-is\n if ((initialValue as IndexableObject)[IS_STORE_PROXY]) {\n return initialValue\n }\n\n // Check if this object was already wrapped (reverse lookup)\n if (RAW_TO_PROXY.has(initialValue)) {\n return RAW_TO_PROXY.get(initialValue) as T\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 // Return true for IS_STORE_PROXY to identify this as a store proxy\n if (prop === IS_STORE_PROXY) {\n return true\n }\n\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\n // Remove \"read-time write\" - direct mutation is now undefined behavior\n // In dev mode, warn once per object if we detect the underlying object was mutated directly\n if (\n isDev &&\n currentValue !== trackedValue &&\n !SKIP_MUTATION_WARNING_PROPS.includes(prop) &&\n !MUTATION_WARNED.has(target)\n ) {\n MUTATION_WARNED.add(target)\n console.warn(`[fict] Use $store for ${String(prop)}.`)\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 const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\n }\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 oldLength = Array.isArray(target) && prop === 'length' ? target.length : undefined\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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 if (signals && signals.length) {\n signals.length(target.length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n if (Array.isArray(target) && prop === 'length') {\n const nextLength = target.length\n if (typeof oldLength === 'number' && nextLength < oldLength) {\n if (signals) {\n for (let i = nextLength; i < oldLength; i += 1) {\n const key = String(i)\n if (signals[key]) {\n signals[key](undefined)\n }\n }\n }\n }\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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 // Register reverse lookup for double-wrap prevention\n RAW_TO_PROXY.set(initialValue, proxy)\n return proxy\n}\n"]}
@@ -0,0 +1,9 @@
1
+ // src/macro-diagnostics.ts
2
+ function createUncompiledMacroError(macroName) {
3
+ const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
4
+ return new Error(isDev ? `${macroName}() compile-only.` : "FICT_E_UNCOMPILED");
5
+ }
6
+
7
+ export { createUncompiledMacroError };
8
+ //# sourceMappingURL=chunk-TKWIPOL2.js.map
9
+ //# sourceMappingURL=chunk-TKWIPOL2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/macro-diagnostics.ts"],"names":[],"mappings":";AAAO,SAAS,2BAA2B,SAAA,EAAwC;AACjF,EAAA,MAAM,KAAA,GACJ,OAAO,OAAA,KAAY,WAAA,GACf,OAAA,GACA,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,GAAA,EAAK,QAAA,KAAa,YAAA;AAClE,EAAA,OAAO,IAAI,KAAA,CAAM,KAAA,GAAQ,CAAA,EAAG,SAAS,qBAAqB,mBAAmB,CAAA;AAC/E","file":"chunk-TKWIPOL2.js","sourcesContent":["export function createUncompiledMacroError(macroName: '$state' | '$effect'): Error {\n const isDev =\n typeof __DEV__ !== 'undefined'\n ? __DEV__\n : typeof process === 'undefined' || process.env?.NODE_ENV !== 'production'\n return new Error(isDev ? `${macroName}() compile-only.` : 'FICT_E_UNCOMPILED')\n}\n"]}
package/dist/index.cjs CHANGED
@@ -3,13 +3,17 @@
3
3
  var runtime = require('@fictjs/runtime');
4
4
  var advanced = require('@fictjs/runtime/advanced');
5
5
 
6
- // src/index.ts
6
+ // src/macro-diagnostics.ts
7
+ function createUncompiledMacroError(macroName) {
8
+ const isDev2 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
9
+ return new Error(isDev2 ? `${macroName}() compile-only.` : "FICT_E_UNCOMPILED");
10
+ }
7
11
  var IS_STORE_PROXY = Symbol("fict-store-proxy");
8
12
  var RAW_TO_PROXY = /* @__PURE__ */ new WeakMap();
9
13
  var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
10
14
  var isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
11
- var MUTATION_WARNED = /* @__PURE__ */ new WeakMap();
12
- var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
15
+ var MUTATION_WARNED = /* @__PURE__ */ new WeakSet();
16
+ var SKIP_MUTATION_WARNING_PROPS = [
13
17
  "constructor",
14
18
  "prototype",
15
19
  "__proto__",
@@ -22,7 +26,7 @@ var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
22
26
  Symbol.toStringTag,
23
27
  Symbol.iterator,
24
28
  Symbol.toPrimitive
25
- ]);
29
+ ];
26
30
  var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
27
31
  var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
28
32
  var ITERATE_KEY = Symbol("iterate");
@@ -66,18 +70,9 @@ function $store(initialValue) {
66
70
  const signal = getSignal(target, prop);
67
71
  const trackedValue = signal();
68
72
  const currentValue = Reflect.get(target, prop, receiver ?? proxy);
69
- if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.has(prop)) {
70
- let warnedProps = MUTATION_WARNED.get(target);
71
- if (!warnedProps) {
72
- warnedProps = /* @__PURE__ */ new Set();
73
- MUTATION_WARNED.set(target, warnedProps);
74
- }
75
- if (!warnedProps.has(prop)) {
76
- warnedProps.add(prop);
77
- console.warn(
78
- `[fict] Direct mutation detected for "${String(prop)}"; mutate via $store proxy.`
79
- );
80
- }
73
+ if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.includes(prop) && !MUTATION_WARNED.has(target)) {
74
+ MUTATION_WARNED.add(target);
75
+ console.warn(`[fict] Use $store for ${String(prop)}.`);
81
76
  }
82
77
  if (typeof currentValue === "function") {
83
78
  let boundMethods = BOUND_METHOD_CACHE.get(target);
@@ -130,20 +125,18 @@ function $store(initialValue) {
130
125
  triggerIteration(target);
131
126
  }
132
127
  if (Array.isArray(target) && prop !== "length") {
133
- const signals2 = SIGNAL_CACHE.get(target);
134
- if (signals2 && signals2.length) {
135
- signals2.length(target.length);
128
+ if (signals && signals.length) {
129
+ signals.length(target.length);
136
130
  }
137
131
  }
138
132
  if (Array.isArray(target) && prop === "length") {
139
133
  const nextLength = target.length;
140
134
  if (typeof oldLength === "number" && nextLength < oldLength) {
141
- const signals2 = SIGNAL_CACHE.get(target);
142
- if (signals2) {
135
+ if (signals) {
143
136
  for (let i = nextLength; i < oldLength; i += 1) {
144
137
  const key = String(i);
145
- if (signals2[key]) {
146
- signals2[key](void 0);
138
+ if (signals[key]) {
139
+ signals[key](void 0);
147
140
  }
148
141
  }
149
142
  }
@@ -187,10 +180,10 @@ function $store(initialValue) {
187
180
 
188
181
  // src/index.ts
189
182
  function $state(_initialValue) {
190
- throw new Error("$state() is a compiler macro and should be transformed at compile time");
183
+ throw createUncompiledMacroError("$state");
191
184
  }
192
185
  function $effect(_fn) {
193
- throw new Error("$effect() is a compiler macro and should be transformed at compile time");
186
+ throw createUncompiledMacroError("$effect");
194
187
  }
195
188
 
196
189
  Object.defineProperty(exports, "$memo", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts","../src/index.ts"],"names":["createSignal","signals"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @fileoverview Deep reactive store implementation for Fict.\n *\n * $store creates a deeply reactive proxy that tracks property access at the path level.\n * Unlike $state (which is shallow), $store allows direct mutation of nested properties.\n *\n * @example\n * ```typescript\n * const user = $store({ name: 'Alice', address: { city: 'London' } })\n * user.address.city = 'Paris' // Fine-grained reactive update\n * ```\n */\n\nimport { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\n/** Function type for bound methods */\ntype AnyFn = (...args: unknown[]) => unknown\n\n/** Cache entry for bound methods to preserve identity */\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\n/** Type for objects with indexable properties */\ntype IndexableObject = Record<string | symbol, unknown>\n\n/** Symbol to mark proxies and prevent double-wrapping */\nconst IS_STORE_PROXY = Symbol('fict-store-proxy')\n\n/** WeakSet to track raw objects that have been proxied (for reverse lookup) */\nconst RAW_TO_PROXY = new WeakMap<object, object>()\n\n/** Cache of proxied objects to avoid duplicate proxies */\nconst PROXY_CACHE = new WeakMap<object, unknown>()\n\n/** Dev mode detection */\nconst isDev =\n typeof __DEV__ !== 'undefined'\n ? __DEV__\n : typeof process === 'undefined' || process.env?.NODE_ENV !== 'production'\n\n/** Track if we've warned about direct mutation for a specific target+property */\nconst MUTATION_WARNED = new WeakMap<object, Set<string | symbol>>()\n\n/** Properties to skip for direct mutation warning (built-in/internal properties) */\nconst SKIP_MUTATION_WARNING_PROPS = new Set<string | symbol>([\n 'constructor',\n 'prototype',\n '__proto__',\n 'toString',\n 'valueOf',\n 'toLocaleString',\n 'hasOwnProperty',\n 'isPrototypeOf',\n 'propertyIsEnumerable',\n Symbol.toStringTag,\n Symbol.iterator,\n Symbol.toPrimitive,\n])\n\n/** Cache of signals per object property */\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\n\n/** Cache of bound methods to preserve function identity across reads */\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\n\n/** Special key for tracking iteration (Object.keys, for-in, etc.) */\nconst ITERATE_KEY = Symbol('iterate')\n\n/**\n * Get or create a signal for a specific property on a target object.\n * @internal\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 IndexableObject)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\n/**\n * Trigger iteration signal to notify consumers that keys have changed.\n * @internal\n */\nfunction triggerIteration(target: object): void {\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\n/**\n * Create a deep reactive store using Proxy.\n *\n * Unlike `$state` (which is shallow and compiler-transformed), `$store` provides:\n * - **Deep reactivity**: Nested objects are automatically wrapped in proxies\n * - **Direct mutation**: Modify properties directly without spread operators\n * - **Path-level tracking**: Only components reading changed paths re-render\n *\n * @param initialValue - The initial object to make reactive\n * @returns A reactive proxy of the object\n *\n * @example\n * ```tsx\n * import { $store } from 'fict'\n *\n * const form = $store({\n * user: { name: '', email: '' },\n * settings: { theme: 'light' }\n * })\n *\n * // Direct mutation works\n * form.user.name = 'Alice'\n *\n * // In JSX - only updates when form.user.name changes\n * <input value={form.user.name} />\n * ```\n *\n * @public\n */\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n // Prevent double-wrapping - if already a store proxy, return as-is\n if ((initialValue as IndexableObject)[IS_STORE_PROXY]) {\n return initialValue\n }\n\n // Check if this object was already wrapped (reverse lookup)\n if (RAW_TO_PROXY.has(initialValue)) {\n return RAW_TO_PROXY.get(initialValue) as T\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 // Return true for IS_STORE_PROXY to identify this as a store proxy\n if (prop === IS_STORE_PROXY) {\n return true\n }\n\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\n // Remove \"read-time write\" - direct mutation is now undefined behavior\n // In dev mode, warn once per property if we detect the underlying object was mutated directly\n if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.has(prop)) {\n let warnedProps = MUTATION_WARNED.get(target)\n if (!warnedProps) {\n warnedProps = new Set()\n MUTATION_WARNED.set(target, warnedProps)\n }\n if (!warnedProps.has(prop)) {\n warnedProps.add(prop)\n console.warn(\n `[fict] Direct mutation detected for \"${String(prop)}\"; mutate via $store proxy.`,\n )\n }\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 const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\n }\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 oldLength = Array.isArray(target) && prop === 'length' ? target.length : undefined\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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.length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n if (Array.isArray(target) && prop === 'length') {\n const nextLength = target.length\n if (typeof oldLength === 'number' && nextLength < oldLength) {\n const signals = SIGNAL_CACHE.get(target)\n if (signals) {\n for (let i = nextLength; i < oldLength; i += 1) {\n const key = String(i)\n if (signals[key]) {\n signals[key](undefined)\n }\n }\n }\n }\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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 // Register reverse lookup for double-wrap prevention\n RAW_TO_PROXY.set(initialValue, proxy)\n return proxy\n}\n","/**\n * @fileoverview Fict Framework - Complete API\n *\n * This is the main entry point for the Fict framework.\n *\n * ## Recommended Import Pattern (v1.0+)\n *\n * ```typescript\n * // Core public API (most users need only this)\n * // Use $state in components (compiler-transformed)\n * // Use $store for cross-component shared state\n * import { $store, render } from 'fict'\n *\n * // Async utilities\n * import { resource, lazy } from 'fict/plus'\n *\n * // Advanced APIs (escape hatches, library authors)\n * import { createSignal, createContext, createScope } from 'fict/advanced'\n * ```\n *\n * ## State Management Guide\n *\n * | Use Case | API |\n * |----------|-----|\n * | Component-local state | `$state` (compiler-transformed) |\n * | Derived values / side effects | JS + auto-derived + `$effect` |\n * | Cross-component (large objects, deep mutation) | `$store` |\n * | Cross-component (scalar/lightweight, library-level) | `createSignal` (advanced) |\n * | Cross-component (subtree scope, SSR isolation) | `Context` (advanced) |\n *\n * @public\n * @packageDocumentation\n */\n\n// Re-export everything from runtime\nexport * from '@fictjs/runtime'\n\n// Re-export commonly used advanced APIs for convenience\nexport { createSelector, createScope, runInScope } from '@fictjs/runtime/advanced'\n\n// ============================================================================\n// Convenience Aliases\n// ============================================================================\n\n/**\n * Alias for createMemo.\n * Creates a memoized value that only recomputes when dependencies change.\n *\n * @example\n * ```tsx\n * const fullName = $memo(() => firstName + ' ' + lastName)\n * ```\n *\n * @public\n */\nexport { createMemo as $memo } from '@fictjs/runtime'\n\n// ============================================================================\n// Deep Reactive Store (Proxy-based)\n// ============================================================================\n\n/**\n * Create a deep reactive store using Proxy.\n * Unlike createStore, $store allows direct mutation.\n *\n * @example\n * ```tsx\n * const user = $store({ name: 'Alice', address: { city: 'Beijing' } })\n * user.name = 'Bob' // Reactive update\n * user.address.city = 'Shanghai' // Deep reactive\n * ```\n *\n * @public\n */\nexport { $store } from './store'\n\n// ============================================================================\n// Compiler Macros (transformed at compile time)\n// ============================================================================\n\n/**\n * Compiler macro for reactive state.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * let count = $state(0)\n * count++ // Reactive update\n * ```\n *\n * @public\n */\nexport function $state<T>(_initialValue: T): T {\n // This function is never called at runtime - the compiler transforms it\n throw new Error('$state() is a compiler macro and should be transformed at compile time')\n}\n\n/**\n * Compiler macro for reactive effects.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * $effect(() => {\n * console.log('count changed:', count)\n * })\n * ```\n *\n * @public\n */\nexport function $effect(_fn: () => void | (() => void)): void {\n // This function is never called at runtime - the compiler transforms it\n throw new Error('$effect() is a compiler macro and should be transformed at compile time')\n}\n"]}
1
+ {"version":3,"sources":["../src/macro-diagnostics.ts","../src/store.ts","../src/index.ts"],"names":["isDev","createSignal"],"mappings":"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","file":"index.cjs","sourcesContent":["export function createUncompiledMacroError(macroName: '$state' | '$effect'): Error {\n const isDev =\n typeof __DEV__ !== 'undefined'\n ? __DEV__\n : typeof process === 'undefined' || process.env?.NODE_ENV !== 'production'\n return new Error(isDev ? `${macroName}() compile-only.` : 'FICT_E_UNCOMPILED')\n}\n","/**\n * @fileoverview Deep reactive store implementation for Fict.\n *\n * $store creates a deeply reactive proxy that tracks property access at the path level.\n * Unlike $state (which is shallow), $store allows direct mutation of nested properties.\n *\n * @example\n * ```typescript\n * const user = $store({ name: 'Alice', address: { city: 'London' } })\n * user.address.city = 'Paris' // Fine-grained reactive update\n * ```\n */\n\nimport { createSignal, type Signal } from '@fictjs/runtime/advanced'\n\n/** Function type for bound methods */\ntype AnyFn = (...args: unknown[]) => unknown\n\n/** Cache entry for bound methods to preserve identity */\ninterface BoundMethodEntry {\n ref: AnyFn\n bound: AnyFn\n}\n\n/** Type for objects with indexable properties */\ntype IndexableObject = Record<string | symbol, unknown>\n\n/** Symbol to mark proxies and prevent double-wrapping */\nconst IS_STORE_PROXY = Symbol('fict-store-proxy')\n\n/** WeakSet to track raw objects that have been proxied (for reverse lookup) */\nconst RAW_TO_PROXY = new WeakMap<object, object>()\n\n/** Cache of proxied objects to avoid duplicate proxies */\nconst PROXY_CACHE = new WeakMap<object, unknown>()\n\n/** Dev mode detection */\nconst isDev =\n typeof __DEV__ !== 'undefined'\n ? __DEV__\n : typeof process === 'undefined' || process.env?.NODE_ENV !== 'production'\n\n/** Track if we've warned about direct mutation for a target object */\nconst MUTATION_WARNED = new WeakSet<object>()\n\n/** Properties to skip for direct mutation warning (built-in/internal properties) */\nconst SKIP_MUTATION_WARNING_PROPS: (string | symbol)[] = [\n 'constructor',\n 'prototype',\n '__proto__',\n 'toString',\n 'valueOf',\n 'toLocaleString',\n 'hasOwnProperty',\n 'isPrototypeOf',\n 'propertyIsEnumerable',\n Symbol.toStringTag,\n Symbol.iterator,\n Symbol.toPrimitive,\n]\n\n/** Cache of signals per object property */\nconst SIGNAL_CACHE = new WeakMap<object, Record<string | symbol, Signal<unknown>>>()\n\n/** Cache of bound methods to preserve function identity across reads */\nconst BOUND_METHOD_CACHE = new WeakMap<object, Map<string | symbol, BoundMethodEntry>>()\n\n/** Special key for tracking iteration (Object.keys, for-in, etc.) */\nconst ITERATE_KEY = Symbol('iterate')\n\n/**\n * Get or create a signal for a specific property on a target object.\n * @internal\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 IndexableObject)[prop]\n signals[prop] = createSignal(initial)\n }\n return signals[prop]\n}\n\n/**\n * Trigger iteration signal to notify consumers that keys have changed.\n * @internal\n */\nfunction triggerIteration(target: object): void {\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\n/**\n * Create a deep reactive store using Proxy.\n *\n * Unlike `$state` (which is shallow and compiler-transformed), `$store` provides:\n * - **Deep reactivity**: Nested objects are automatically wrapped in proxies\n * - **Direct mutation**: Modify properties directly without spread operators\n * - **Path-level tracking**: Only components reading changed paths re-render\n *\n * @param initialValue - The initial object to make reactive\n * @returns A reactive proxy of the object\n *\n * @example\n * ```tsx\n * import { $store } from 'fict'\n *\n * const form = $store({\n * user: { name: '', email: '' },\n * settings: { theme: 'light' }\n * })\n *\n * // Direct mutation works\n * form.user.name = 'Alice'\n *\n * // In JSX - only updates when form.user.name changes\n * <input value={form.user.name} />\n * ```\n *\n * @public\n */\nexport function $store<T extends object>(initialValue: T): T {\n if (typeof initialValue !== 'object' || initialValue === null) {\n return initialValue\n }\n\n // Prevent double-wrapping - if already a store proxy, return as-is\n if ((initialValue as IndexableObject)[IS_STORE_PROXY]) {\n return initialValue\n }\n\n // Check if this object was already wrapped (reverse lookup)\n if (RAW_TO_PROXY.has(initialValue)) {\n return RAW_TO_PROXY.get(initialValue) as T\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 // Return true for IS_STORE_PROXY to identify this as a store proxy\n if (prop === IS_STORE_PROXY) {\n return true\n }\n\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\n // Remove \"read-time write\" - direct mutation is now undefined behavior\n // In dev mode, warn once per object if we detect the underlying object was mutated directly\n if (\n isDev &&\n currentValue !== trackedValue &&\n !SKIP_MUTATION_WARNING_PROPS.includes(prop) &&\n !MUTATION_WARNED.has(target)\n ) {\n MUTATION_WARNED.add(target)\n console.warn(`[fict] Use $store for ${String(prop)}.`)\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 const boundMethods = BOUND_METHOD_CACHE.get(target)\n if (boundMethods && boundMethods.has(prop)) {\n boundMethods.delete(prop)\n if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\n }\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 oldLength = Array.isArray(target) && prop === 'length' ? target.length : undefined\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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 if (signals && signals.length) {\n signals.length(target.length)\n }\n }\n\n // If it's an array and length changed implicitly, we might need to handle it.\n if (Array.isArray(target) && prop === 'length') {\n const nextLength = target.length\n if (typeof oldLength === 'number' && nextLength < oldLength) {\n if (signals) {\n for (let i = nextLength; i < oldLength; i += 1) {\n const key = String(i)\n if (signals[key]) {\n signals[key](undefined)\n }\n }\n }\n }\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 if (boundMethods.size === 0) {\n BOUND_METHOD_CACHE.delete(target)\n }\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 // Register reverse lookup for double-wrap prevention\n RAW_TO_PROXY.set(initialValue, proxy)\n return proxy\n}\n","/**\n * @fileoverview Fict Framework - Complete API\n *\n * This is the main entry point for the Fict framework.\n *\n * ## Recommended Import Pattern (v1.0+)\n *\n * ```typescript\n * // Core public API (most users need only this)\n * // Use $state in components (compiler-transformed)\n * // Use $store for cross-component shared state\n * import { $store, render } from 'fict'\n *\n * // Async utilities\n * import { resource, lazy } from 'fict/plus'\n *\n * // Advanced APIs (escape hatches, library authors)\n * import { createSignal, createContext, createScope } from 'fict/advanced'\n * ```\n *\n * ## State Management Guide\n *\n * | Use Case | API |\n * |----------|-----|\n * | Component-local state | `$state` (compiler-transformed) |\n * | Derived values / side effects | JS + auto-derived + `$effect` |\n * | Cross-component (large objects, deep mutation) | `$store` |\n * | Cross-component (scalar/lightweight, library-level) | `createSignal` (advanced) |\n * | Cross-component (subtree scope, SSR isolation) | `Context` (advanced) |\n *\n * @public\n * @packageDocumentation\n */\n\nimport { createUncompiledMacroError } from './macro-diagnostics'\n\n// Re-export everything from runtime\nexport * from '@fictjs/runtime'\n\n// Re-export commonly used advanced APIs for convenience. Manual reactive getter\n// markers stay in `fict/advanced` so the main entrypoint remains user-facing.\nexport { createSelector, createScope, runInScope } from '@fictjs/runtime/advanced'\n\n// ============================================================================\n// Convenience Aliases\n// ============================================================================\n\n/**\n * Alias for createMemo.\n * Creates a memoized value that only recomputes when dependencies change.\n *\n * @example\n * ```tsx\n * const fullName = $memo(() => firstName + ' ' + lastName)\n * ```\n *\n * @public\n */\nexport { createMemo as $memo } from '@fictjs/runtime'\n\n// ============================================================================\n// Deep Reactive Store (Proxy-based)\n// ============================================================================\n\n/**\n * Create a deep reactive store using Proxy.\n * Unlike createStore, $store allows direct mutation.\n *\n * @example\n * ```tsx\n * const user = $store({ name: 'Alice', address: { city: 'Beijing' } })\n * user.name = 'Bob' // Reactive update\n * user.address.city = 'Shanghai' // Deep reactive\n * ```\n *\n * @public\n */\nexport { $store } from './store'\n\n// ============================================================================\n// Compiler Macros (transformed at compile time)\n// ============================================================================\n\n/**\n * Compiler macro for reactive state.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * let count = $state(0)\n * count++ // Reactive update\n * ```\n *\n * @public\n */\nexport function $state<T>(_initialValue: T): T {\n // This function is never called at runtime - the compiler transforms it\n throw createUncompiledMacroError('$state')\n}\n\n/**\n * Compiler macro for reactive effects.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * $effect(() => {\n * console.log('count changed:', count)\n * })\n * ```\n *\n * @public\n */\nexport function $effect(_fn: () => void | (() => void)): void {\n // This function is never called at runtime - the compiler transforms it\n throw createUncompiledMacroError('$effect')\n}\n"]}
package/dist/index.js CHANGED
@@ -1,13 +1,14 @@
1
- export { $store } from './chunk-43IPAXWW.js';
1
+ import { createUncompiledMacroError } from './chunk-TKWIPOL2.js';
2
+ export { $store } from './chunk-7CM2UZ6M.js';
2
3
  export * from '@fictjs/runtime';
3
4
  export { createMemo as $memo } from '@fictjs/runtime';
4
5
  export { createScope, createSelector, runInScope } from '@fictjs/runtime/advanced';
5
6
 
6
7
  function $state(_initialValue) {
7
- throw new Error("$state() is a compiler macro and should be transformed at compile time");
8
+ throw createUncompiledMacroError("$state");
8
9
  }
9
10
  function $effect(_fn) {
10
- throw new Error("$effect() is a compiler macro and should be transformed at compile time");
11
+ throw createUncompiledMacroError("$effect");
11
12
  }
12
13
 
13
14
  export { $effect, $state };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;AA4FO,SAAS,OAAU,aAAA,EAAqB;AAE7C,EAAA,MAAM,IAAI,MAAM,wEAAwE,CAAA;AAC1F;AAeO,SAAS,QAAQ,GAAA,EAAsC;AAE5D,EAAA,MAAM,IAAI,MAAM,yEAAyE,CAAA;AAC3F","file":"index.js","sourcesContent":["/**\n * @fileoverview Fict Framework - Complete API\n *\n * This is the main entry point for the Fict framework.\n *\n * ## Recommended Import Pattern (v1.0+)\n *\n * ```typescript\n * // Core public API (most users need only this)\n * // Use $state in components (compiler-transformed)\n * // Use $store for cross-component shared state\n * import { $store, render } from 'fict'\n *\n * // Async utilities\n * import { resource, lazy } from 'fict/plus'\n *\n * // Advanced APIs (escape hatches, library authors)\n * import { createSignal, createContext, createScope } from 'fict/advanced'\n * ```\n *\n * ## State Management Guide\n *\n * | Use Case | API |\n * |----------|-----|\n * | Component-local state | `$state` (compiler-transformed) |\n * | Derived values / side effects | JS + auto-derived + `$effect` |\n * | Cross-component (large objects, deep mutation) | `$store` |\n * | Cross-component (scalar/lightweight, library-level) | `createSignal` (advanced) |\n * | Cross-component (subtree scope, SSR isolation) | `Context` (advanced) |\n *\n * @public\n * @packageDocumentation\n */\n\n// Re-export everything from runtime\nexport * from '@fictjs/runtime'\n\n// Re-export commonly used advanced APIs for convenience\nexport { createSelector, createScope, runInScope } from '@fictjs/runtime/advanced'\n\n// ============================================================================\n// Convenience Aliases\n// ============================================================================\n\n/**\n * Alias for createMemo.\n * Creates a memoized value that only recomputes when dependencies change.\n *\n * @example\n * ```tsx\n * const fullName = $memo(() => firstName + ' ' + lastName)\n * ```\n *\n * @public\n */\nexport { createMemo as $memo } from '@fictjs/runtime'\n\n// ============================================================================\n// Deep Reactive Store (Proxy-based)\n// ============================================================================\n\n/**\n * Create a deep reactive store using Proxy.\n * Unlike createStore, $store allows direct mutation.\n *\n * @example\n * ```tsx\n * const user = $store({ name: 'Alice', address: { city: 'Beijing' } })\n * user.name = 'Bob' // Reactive update\n * user.address.city = 'Shanghai' // Deep reactive\n * ```\n *\n * @public\n */\nexport { $store } from './store'\n\n// ============================================================================\n// Compiler Macros (transformed at compile time)\n// ============================================================================\n\n/**\n * Compiler macro for reactive state.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * let count = $state(0)\n * count++ // Reactive update\n * ```\n *\n * @public\n */\nexport function $state<T>(_initialValue: T): T {\n // This function is never called at runtime - the compiler transforms it\n throw new Error('$state() is a compiler macro and should be transformed at compile time')\n}\n\n/**\n * Compiler macro for reactive effects.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * $effect(() => {\n * console.log('count changed:', count)\n * })\n * ```\n *\n * @public\n */\nexport function $effect(_fn: () => void | (() => void)): void {\n // This function is never called at runtime - the compiler transforms it\n throw new Error('$effect() is a compiler macro and should be transformed at compile time')\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AA+FO,SAAS,OAAU,aAAA,EAAqB;AAE7C,EAAA,MAAM,2BAA2B,QAAQ,CAAA;AAC3C;AAeO,SAAS,QAAQ,GAAA,EAAsC;AAE5D,EAAA,MAAM,2BAA2B,SAAS,CAAA;AAC5C","file":"index.js","sourcesContent":["/**\n * @fileoverview Fict Framework - Complete API\n *\n * This is the main entry point for the Fict framework.\n *\n * ## Recommended Import Pattern (v1.0+)\n *\n * ```typescript\n * // Core public API (most users need only this)\n * // Use $state in components (compiler-transformed)\n * // Use $store for cross-component shared state\n * import { $store, render } from 'fict'\n *\n * // Async utilities\n * import { resource, lazy } from 'fict/plus'\n *\n * // Advanced APIs (escape hatches, library authors)\n * import { createSignal, createContext, createScope } from 'fict/advanced'\n * ```\n *\n * ## State Management Guide\n *\n * | Use Case | API |\n * |----------|-----|\n * | Component-local state | `$state` (compiler-transformed) |\n * | Derived values / side effects | JS + auto-derived + `$effect` |\n * | Cross-component (large objects, deep mutation) | `$store` |\n * | Cross-component (scalar/lightweight, library-level) | `createSignal` (advanced) |\n * | Cross-component (subtree scope, SSR isolation) | `Context` (advanced) |\n *\n * @public\n * @packageDocumentation\n */\n\nimport { createUncompiledMacroError } from './macro-diagnostics'\n\n// Re-export everything from runtime\nexport * from '@fictjs/runtime'\n\n// Re-export commonly used advanced APIs for convenience. Manual reactive getter\n// markers stay in `fict/advanced` so the main entrypoint remains user-facing.\nexport { createSelector, createScope, runInScope } from '@fictjs/runtime/advanced'\n\n// ============================================================================\n// Convenience Aliases\n// ============================================================================\n\n/**\n * Alias for createMemo.\n * Creates a memoized value that only recomputes when dependencies change.\n *\n * @example\n * ```tsx\n * const fullName = $memo(() => firstName + ' ' + lastName)\n * ```\n *\n * @public\n */\nexport { createMemo as $memo } from '@fictjs/runtime'\n\n// ============================================================================\n// Deep Reactive Store (Proxy-based)\n// ============================================================================\n\n/**\n * Create a deep reactive store using Proxy.\n * Unlike createStore, $store allows direct mutation.\n *\n * @example\n * ```tsx\n * const user = $store({ name: 'Alice', address: { city: 'Beijing' } })\n * user.name = 'Bob' // Reactive update\n * user.address.city = 'Shanghai' // Deep reactive\n * ```\n *\n * @public\n */\nexport { $store } from './store'\n\n// ============================================================================\n// Compiler Macros (transformed at compile time)\n// ============================================================================\n\n/**\n * Compiler macro for reactive state.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * let count = $state(0)\n * count++ // Reactive update\n * ```\n *\n * @public\n */\nexport function $state<T>(_initialValue: T): T {\n // This function is never called at runtime - the compiler transforms it\n throw createUncompiledMacroError('$state')\n}\n\n/**\n * Compiler macro for reactive effects.\n * This is transformed at compile time and should never be called at runtime.\n *\n * @example\n * ```tsx\n * $effect(() => {\n * console.log('count changed:', count)\n * })\n * ```\n *\n * @public\n */\nexport function $effect(_fn: () => void | (() => void)): void {\n // This function is never called at runtime - the compiler transforms it\n throw createUncompiledMacroError('$effect')\n}\n"]}
package/dist/plus.cjs CHANGED
@@ -8,8 +8,8 @@ var IS_STORE_PROXY = Symbol("fict-store-proxy");
8
8
  var RAW_TO_PROXY = /* @__PURE__ */ new WeakMap();
9
9
  var PROXY_CACHE = /* @__PURE__ */ new WeakMap();
10
10
  var isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
11
- var MUTATION_WARNED = /* @__PURE__ */ new WeakMap();
12
- var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
11
+ var MUTATION_WARNED = /* @__PURE__ */ new WeakSet();
12
+ var SKIP_MUTATION_WARNING_PROPS = [
13
13
  "constructor",
14
14
  "prototype",
15
15
  "__proto__",
@@ -22,7 +22,7 @@ var SKIP_MUTATION_WARNING_PROPS = /* @__PURE__ */ new Set([
22
22
  Symbol.toStringTag,
23
23
  Symbol.iterator,
24
24
  Symbol.toPrimitive
25
- ]);
25
+ ];
26
26
  var SIGNAL_CACHE = /* @__PURE__ */ new WeakMap();
27
27
  var BOUND_METHOD_CACHE = /* @__PURE__ */ new WeakMap();
28
28
  var ITERATE_KEY = Symbol("iterate");
@@ -66,18 +66,9 @@ function $store(initialValue) {
66
66
  const signal = getSignal(target, prop);
67
67
  const trackedValue = signal();
68
68
  const currentValue = Reflect.get(target, prop, receiver ?? proxy);
69
- if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.has(prop)) {
70
- let warnedProps = MUTATION_WARNED.get(target);
71
- if (!warnedProps) {
72
- warnedProps = /* @__PURE__ */ new Set();
73
- MUTATION_WARNED.set(target, warnedProps);
74
- }
75
- if (!warnedProps.has(prop)) {
76
- warnedProps.add(prop);
77
- console.warn(
78
- `[fict] Direct mutation detected for "${String(prop)}"; mutate via $store proxy.`
79
- );
80
- }
69
+ if (isDev && currentValue !== trackedValue && !SKIP_MUTATION_WARNING_PROPS.includes(prop) && !MUTATION_WARNED.has(target)) {
70
+ MUTATION_WARNED.add(target);
71
+ console.warn(`[fict] Use $store for ${String(prop)}.`);
81
72
  }
82
73
  if (typeof currentValue === "function") {
83
74
  let boundMethods = BOUND_METHOD_CACHE.get(target);
@@ -130,20 +121,18 @@ function $store(initialValue) {
130
121
  triggerIteration(target);
131
122
  }
132
123
  if (Array.isArray(target) && prop !== "length") {
133
- const signals2 = SIGNAL_CACHE.get(target);
134
- if (signals2 && signals2.length) {
135
- signals2.length(target.length);
124
+ if (signals && signals.length) {
125
+ signals.length(target.length);
136
126
  }
137
127
  }
138
128
  if (Array.isArray(target) && prop === "length") {
139
129
  const nextLength = target.length;
140
130
  if (typeof oldLength === "number" && nextLength < oldLength) {
141
- const signals2 = SIGNAL_CACHE.get(target);
142
- if (signals2) {
131
+ if (signals) {
143
132
  for (let i = nextLength; i < oldLength; i += 1) {
144
133
  const key = String(i);
145
- if (signals2[key]) {
146
- signals2[key](void 0);
134
+ if (signals[key]) {
135
+ signals[key](void 0);
147
136
  }
148
137
  }
149
138
  }
@@ -196,7 +185,7 @@ function resource(optionsOrFetcher) {
196
185
  const cacheOptions = typeof optionsOrFetcher === "object" ? optionsOrFetcher.cache ?? {} : {};
197
186
  const resolvedCacheOptions = { ...defaultCacheOptions, ...cacheOptions };
198
187
  const cache = /* @__PURE__ */ new Map();
199
- const readArgs = (argsAccessor) => typeof argsAccessor === "function" ? argsAccessor() : argsAccessor;
188
+ const readArgs = (argsAccessor) => advanced.isReactive(argsAccessor) ? argsAccessor() : argsAccessor;
200
189
  const computeKey = (argsAccessor) => {
201
190
  const argsValue = readArgs(argsAccessor);
202
191
  if (typeof optionsOrFetcher === "object" && optionsOrFetcher.key !== void 0) {
@@ -208,7 +197,7 @@ function resource(optionsOrFetcher) {
208
197
  const readResetToken = () => {
209
198
  if (typeof optionsOrFetcher !== "object") return void 0;
210
199
  const reset = optionsOrFetcher.reset;
211
- if (typeof reset === "function" && reset.length === 0) {
200
+ if (advanced.isReactive(reset)) {
212
201
  return reset();
213
202
  }
214
203
  return reset;