@netrojs/fnetro 0.1.2

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/core.d.ts ADDED
@@ -0,0 +1,200 @@
1
+ import { Hono, MiddlewareHandler, Context } from 'hono';
2
+
3
+ type EffectFn = () => void | (() => void);
4
+ declare const IS_REF: unique symbol;
5
+ declare class ReactiveEffect {
6
+ fn: () => any;
7
+ scheduler?: (() => void) | undefined;
8
+ scope?: EffectScope | undefined;
9
+ deps: Set<ReactiveEffect>[];
10
+ active: boolean;
11
+ cleanup?: () => void;
12
+ computed: boolean;
13
+ constructor(fn: () => any, scheduler?: (() => void) | undefined, scope?: EffectScope | undefined);
14
+ run(): any;
15
+ stop(): void;
16
+ }
17
+ declare class EffectScope {
18
+ effects: ReactiveEffect[];
19
+ cleanups: (() => void)[];
20
+ active: boolean;
21
+ run<T>(fn: () => T): T;
22
+ stop(): void;
23
+ onCleanup(fn: () => void): void;
24
+ }
25
+ declare function effectScope(): EffectScope;
26
+ declare function getCurrentScope(): EffectScope | undefined;
27
+ declare function onScopeDispose(fn: () => void): void;
28
+ declare function effect(fn: EffectFn): () => void;
29
+ interface WatchEffectOptions {
30
+ flush?: 'sync' | 'post';
31
+ onTrack?: (e: any) => void;
32
+ onTrigger?: (e: any) => void;
33
+ }
34
+ declare function watchEffect(fn: EffectFn, opts?: WatchEffectOptions): () => void;
35
+ interface Ref<T = unknown> {
36
+ value: T;
37
+ readonly [IS_REF]: true;
38
+ }
39
+ declare function ref<T>(value: T): Ref<T>;
40
+ declare function shallowRef<T>(value: T): Ref<T>;
41
+ declare function triggerRef(r: Ref): void;
42
+ declare function isRef<T = unknown>(r: unknown): r is Ref<T>;
43
+ declare function unref<T>(r: T | Ref<T>): T;
44
+ declare function toRef<T extends object, K extends keyof T>(obj: T, key: K): Ref<T[K]>;
45
+ declare function toRefs<T extends object>(obj: T): {
46
+ [K in keyof T]: Ref<T[K]>;
47
+ };
48
+ interface WritableComputedRef<T> extends Ref<T> {
49
+ readonly effect: ReactiveEffect;
50
+ }
51
+ interface ComputedRef<T> extends WritableComputedRef<T> {
52
+ readonly value: T;
53
+ }
54
+ declare function computed<T>(getter: () => T): ComputedRef<T>;
55
+ declare function computed<T>(opts: {
56
+ get: () => T;
57
+ set: (v: T) => void;
58
+ }): WritableComputedRef<T>;
59
+ declare function reactive<T extends object>(target: T): T;
60
+ declare function shallowReactive<T extends object>(target: T): T;
61
+ declare function readonly<T extends object>(target: T): Readonly<T>;
62
+ declare function markRaw<T extends object>(value: T): T;
63
+ declare function toRaw<T>(observed: T): T;
64
+ declare function isReactive(value: unknown): boolean;
65
+ declare function isReadonly(value: unknown): boolean;
66
+ type WatchSource<T = unknown> = Ref<T> | ComputedRef<T> | (() => T);
67
+ type MultiSource = WatchSource[] | readonly WatchSource[];
68
+ type MapSources<T, Immediate = false> = {
69
+ [K in keyof T]: T[K] extends WatchSource<infer V> ? Immediate extends true ? V | undefined : V : T[K] extends object ? T[K] : never;
70
+ };
71
+ interface WatchOptions<Immediate = boolean> {
72
+ immediate?: Immediate;
73
+ deep?: boolean;
74
+ once?: boolean;
75
+ }
76
+ type StopHandle = () => void;
77
+ type CleanupFn = (fn: () => void) => void;
78
+ declare function watch<T>(source: WatchSource<T>, cb: (val: T, old: T | undefined, cleanup: CleanupFn) => void, opts?: WatchOptions): StopHandle;
79
+ declare function watch<T extends MultiSource>(source: T, cb: (val: MapSources<T>, old: MapSources<T, true>, cleanup: CleanupFn) => void, opts?: WatchOptions): StopHandle;
80
+ interface FNetroHooks {
81
+ useValue<T>(r: Ref<T> | (() => T)): T;
82
+ useLocalRef<T>(init: T): Ref<T>;
83
+ useLocalReactive<T extends object>(init: T): T;
84
+ }
85
+ declare const __hooks: FNetroHooks;
86
+ /**
87
+ * Subscribe to a Ref or computed getter inside a JSX component.
88
+ * On the server, returns the current value (no reactivity needed).
89
+ * On the client, re-renders the component whenever the value changes.
90
+ *
91
+ * @example
92
+ * const count = ref(0)
93
+ * function Counter() {
94
+ * const n = use(count)
95
+ * return <button onClick={() => count.value++}>{n}</button>
96
+ * }
97
+ */
98
+ declare function use<T>(source: Ref<T> | (() => T)): T;
99
+ /**
100
+ * Create a component-local reactive Ref.
101
+ * Unlike module-level `ref()`, this is scoped to the component lifecycle.
102
+ *
103
+ * @example
104
+ * function Input() {
105
+ * const text = useLocalRef('')
106
+ * return <input value={use(text)} onInput={e => text.value = e.target.value} />
107
+ * }
108
+ */
109
+ declare function useLocalRef<T>(init: T): Ref<T>;
110
+ /**
111
+ * Create a component-local reactive object.
112
+ * @example
113
+ * function Form() {
114
+ * const form = useLocalReactive({ name: '', email: '' })
115
+ * return <input value={form.name} onInput={e => form.name = e.target.value} />
116
+ * }
117
+ */
118
+ declare function useLocalReactive<T extends object>(init: T): T;
119
+ type LoaderCtx = Context;
120
+ type FNetroMiddleware = MiddlewareHandler;
121
+ type AnyJSX = any;
122
+ interface PageDef<TData extends object = {}> {
123
+ readonly __type: 'page';
124
+ path: string;
125
+ /** Middleware applied only to this route */
126
+ middleware?: FNetroMiddleware[];
127
+ /** Server-side data loader. Return value becomes Page props. */
128
+ loader?: (c: LoaderCtx) => TData | Promise<TData>;
129
+ /** Override the group/app layout for this page. Pass `false` to use no layout. */
130
+ layout?: LayoutDef | false;
131
+ /** The JSX page component */
132
+ Page: (props: TData & {
133
+ url: string;
134
+ params: Record<string, string>;
135
+ }) => AnyJSX;
136
+ }
137
+ interface GroupDef {
138
+ readonly __type: 'group';
139
+ /** URL prefix — e.g. '/admin' */
140
+ prefix: string;
141
+ /** Layout override for all pages in this group */
142
+ layout?: LayoutDef | false;
143
+ /** Middleware applied to every route in the group */
144
+ middleware?: FNetroMiddleware[];
145
+ /** Pages and nested groups */
146
+ routes: (PageDef<any> | GroupDef | ApiRouteDef)[];
147
+ }
148
+ interface LayoutDef {
149
+ readonly __type: 'layout';
150
+ Component: (props: {
151
+ children: AnyJSX;
152
+ url: string;
153
+ params: Record<string, string>;
154
+ }) => AnyJSX;
155
+ }
156
+ interface ApiRouteDef {
157
+ readonly __type: 'api';
158
+ /** Mount path — e.g. '/api' or '/api/admin' */
159
+ path: string;
160
+ /** Register raw Hono routes on the provided sub-app */
161
+ register: (app: Hono, middleware: FNetroMiddleware[]) => void;
162
+ }
163
+ interface MiddlewareDef {
164
+ readonly __type: 'middleware';
165
+ handler: FNetroMiddleware;
166
+ }
167
+ interface AppConfig {
168
+ /** Default layout for all pages */
169
+ layout?: LayoutDef;
170
+ /** Global middleware applied before every route */
171
+ middleware?: FNetroMiddleware[];
172
+ /** Top-level routes, groups, and API routes */
173
+ routes: (PageDef<any> | GroupDef | ApiRouteDef)[];
174
+ /** 404 page */
175
+ notFound?: () => AnyJSX;
176
+ }
177
+ declare function definePage<TData extends object = {}>(def: Omit<PageDef<TData>, '__type'>): PageDef<TData>;
178
+ declare function defineGroup(def: Omit<GroupDef, '__type'>): GroupDef;
179
+ declare function defineLayout(Component: LayoutDef['Component']): LayoutDef;
180
+ declare function defineMiddleware(handler: FNetroMiddleware): MiddlewareDef;
181
+ declare function defineApiRoute(path: string, register: ApiRouteDef['register']): ApiRouteDef;
182
+ interface ResolvedRoute {
183
+ fullPath: string;
184
+ page: PageDef<any>;
185
+ layout: LayoutDef | false | undefined;
186
+ middleware: FNetroMiddleware[];
187
+ }
188
+ declare function resolveRoutes(routes: (PageDef<any> | GroupDef | ApiRouteDef)[], options?: {
189
+ prefix?: string;
190
+ middleware?: FNetroMiddleware[];
191
+ layout?: LayoutDef | false;
192
+ }): {
193
+ pages: ResolvedRoute[];
194
+ apis: ApiRouteDef[];
195
+ };
196
+ declare const SPA_HEADER = "x-fnetro-spa";
197
+ declare const STATE_KEY = "__FNETRO_STATE__";
198
+ declare const PARAMS_KEY = "__FNETRO_PARAMS__";
199
+
200
+ export { type AnyJSX, type ApiRouteDef, type AppConfig, type ComputedRef, type EffectFn, EffectScope, type FNetroMiddleware, type GroupDef, type LayoutDef, type LoaderCtx, type MiddlewareDef, type MultiSource, PARAMS_KEY, type PageDef, ReactiveEffect, type Ref, type ResolvedRoute, SPA_HEADER, STATE_KEY, type WatchEffectOptions, type WatchOptions, type WatchSource, type WritableComputedRef, __hooks, computed, defineApiRoute, defineGroup, defineLayout, defineMiddleware, definePage, effect, effectScope, getCurrentScope, isReactive, isReadonly, isRef, markRaw, onScopeDispose, reactive, readonly, ref, resolveRoutes, shallowReactive, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, use, useLocalReactive, useLocalRef, watch, watchEffect };
package/dist/core.js ADDED
@@ -0,0 +1,495 @@
1
+ // core.ts
2
+ var RAW = /* @__PURE__ */ Symbol("raw");
3
+ var IS_REACTIVE = /* @__PURE__ */ Symbol("isReactive");
4
+ var IS_READONLY = /* @__PURE__ */ Symbol("isReadonly");
5
+ var IS_REF = /* @__PURE__ */ Symbol("isRef");
6
+ var MARK_RAW = /* @__PURE__ */ Symbol("markRaw");
7
+ var targetMap = /* @__PURE__ */ new WeakMap();
8
+ var activeEffect = null;
9
+ var shouldTrack = true;
10
+ var trackStack = [];
11
+ function pauseTracking() {
12
+ trackStack.push(shouldTrack);
13
+ shouldTrack = false;
14
+ }
15
+ function resetTracking() {
16
+ shouldTrack = trackStack.pop() ?? true;
17
+ }
18
+ function track(target, key) {
19
+ if (!shouldTrack || !activeEffect) return;
20
+ let depsMap = targetMap.get(target);
21
+ if (!depsMap) targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
22
+ let dep = depsMap.get(key);
23
+ if (!dep) depsMap.set(key, dep = /* @__PURE__ */ new Set());
24
+ trackEffect(activeEffect, dep);
25
+ }
26
+ function trackEffect(effect2, dep) {
27
+ if (!dep.has(effect2)) {
28
+ dep.add(effect2);
29
+ effect2.deps.push(dep);
30
+ }
31
+ }
32
+ function trigger(target, key, newVal, oldVal) {
33
+ const depsMap = targetMap.get(target);
34
+ if (!depsMap) return;
35
+ const effects = [];
36
+ const computedEffects = [];
37
+ depsMap.get(key)?.forEach((e) => {
38
+ if (e !== activeEffect) {
39
+ e.computed ? computedEffects.push(e) : effects.push(e);
40
+ }
41
+ });
42
+ [...computedEffects, ...effects].forEach((e) => {
43
+ if (e.active) e.scheduler ? e.scheduler() : e.run();
44
+ });
45
+ }
46
+ var ReactiveEffect = class {
47
+ constructor(fn, scheduler, scope) {
48
+ this.fn = fn;
49
+ this.scheduler = scheduler;
50
+ this.scope = scope;
51
+ scope?.effects.push(this);
52
+ }
53
+ deps = [];
54
+ active = true;
55
+ cleanup;
56
+ computed = false;
57
+ run() {
58
+ if (!this.active) return this.fn();
59
+ const prevEffect = activeEffect;
60
+ const prevShouldTrack = shouldTrack;
61
+ shouldTrack = true;
62
+ activeEffect = this;
63
+ this.cleanup?.();
64
+ this.cleanup = void 0;
65
+ this.deps.length = 0;
66
+ try {
67
+ const result = this.fn();
68
+ if (typeof result === "function") this.cleanup = result;
69
+ return result;
70
+ } finally {
71
+ activeEffect = prevEffect;
72
+ shouldTrack = prevShouldTrack;
73
+ }
74
+ }
75
+ stop() {
76
+ if (this.active) {
77
+ cleanupEffect(this);
78
+ this.active = false;
79
+ }
80
+ }
81
+ };
82
+ function cleanupEffect(e) {
83
+ e.deps.forEach((dep) => dep.delete(e));
84
+ e.deps.length = 0;
85
+ }
86
+ var activeScope;
87
+ var EffectScope = class {
88
+ effects = [];
89
+ cleanups = [];
90
+ active = true;
91
+ run(fn) {
92
+ const prev = activeScope;
93
+ activeScope = this;
94
+ try {
95
+ return fn();
96
+ } finally {
97
+ activeScope = prev;
98
+ }
99
+ }
100
+ stop() {
101
+ if (this.active) {
102
+ this.effects.forEach((e) => e.stop());
103
+ this.cleanups.forEach((fn) => fn());
104
+ this.active = false;
105
+ }
106
+ }
107
+ onCleanup(fn) {
108
+ this.cleanups.push(fn);
109
+ }
110
+ };
111
+ function effectScope() {
112
+ return new EffectScope();
113
+ }
114
+ function getCurrentScope() {
115
+ return activeScope;
116
+ }
117
+ function onScopeDispose(fn) {
118
+ activeScope?.onCleanup(fn);
119
+ }
120
+ function effect(fn) {
121
+ const e = new ReactiveEffect(fn, void 0, activeScope);
122
+ e.run();
123
+ return () => e.stop();
124
+ }
125
+ function watchEffect(fn, opts) {
126
+ const e = new ReactiveEffect(fn, void 0, activeScope);
127
+ e.run();
128
+ return () => e.stop();
129
+ }
130
+ var refTarget = /* @__PURE__ */ Symbol("refTarget");
131
+ var RefImpl = class {
132
+ constructor(value, shallow = false) {
133
+ this.shallow = shallow;
134
+ this._value = shallow ? value : toReactive(value);
135
+ }
136
+ [IS_REF] = true;
137
+ _value;
138
+ _subscribers = /* @__PURE__ */ new Set();
139
+ get value() {
140
+ track(this, refTarget);
141
+ this._subscribers.forEach((fn) => {
142
+ });
143
+ return this._value;
144
+ }
145
+ set value(next) {
146
+ const newVal = this.shallow ? next : toReactive(next);
147
+ if (!hasChanged(newVal, this._value)) return;
148
+ this._value = newVal;
149
+ trigger(this, refTarget, newVal, this._value);
150
+ this._subscribers.forEach((fn) => fn());
151
+ }
152
+ /** Subscribe for useSyncExternalStore */
153
+ subscribe(fn) {
154
+ this._subscribers.add(fn);
155
+ return () => this._subscribers.delete(fn);
156
+ }
157
+ peek() {
158
+ return this._value;
159
+ }
160
+ };
161
+ function ref(value) {
162
+ return isRef(value) ? value : new RefImpl(value);
163
+ }
164
+ function shallowRef(value) {
165
+ return new RefImpl(value, true);
166
+ }
167
+ function triggerRef(r) {
168
+ if (r instanceof RefImpl) {
169
+ trigger(r, refTarget);
170
+ r._subscribers.forEach((fn) => fn());
171
+ }
172
+ }
173
+ function isRef(r) {
174
+ return !!r && typeof r === "object" && r[IS_REF] === true;
175
+ }
176
+ function unref(r) {
177
+ return isRef(r) ? r.value : r;
178
+ }
179
+ function toRef(obj, key) {
180
+ const r = new RefImpl(void 0, false);
181
+ Object.defineProperty(r, "value", {
182
+ get() {
183
+ track(r, refTarget);
184
+ return obj[key];
185
+ },
186
+ set(v) {
187
+ obj[key] = v;
188
+ trigger(r, refTarget, v, obj[key]);
189
+ }
190
+ });
191
+ return r;
192
+ }
193
+ function toRefs(obj) {
194
+ const result = {};
195
+ for (const key in obj) result[key] = toRef(obj, key);
196
+ return result;
197
+ }
198
+ var ComputedRefImpl = class {
199
+ constructor(getter, setter) {
200
+ this.setter = setter;
201
+ this.effect = new ReactiveEffect(getter, () => {
202
+ if (!this._dirty) {
203
+ this._dirty = true;
204
+ trigger(this, refTarget);
205
+ this._subscribers.forEach((fn) => fn());
206
+ }
207
+ }, activeScope);
208
+ this.effect.computed = true;
209
+ }
210
+ [IS_REF] = true;
211
+ effect;
212
+ _value;
213
+ _dirty = true;
214
+ _subscribers = /* @__PURE__ */ new Set();
215
+ get value() {
216
+ track(this, refTarget);
217
+ if (this._dirty) {
218
+ this._dirty = false;
219
+ this._value = this.effect.run();
220
+ }
221
+ return this._value;
222
+ }
223
+ set value(v) {
224
+ this.setter?.(v);
225
+ }
226
+ subscribe(fn) {
227
+ this._subscribers.add(fn);
228
+ return () => this._subscribers.delete(fn);
229
+ }
230
+ peek() {
231
+ return this._value;
232
+ }
233
+ };
234
+ function computed(arg) {
235
+ if (typeof arg === "function") {
236
+ return new ComputedRefImpl(arg);
237
+ }
238
+ return new ComputedRefImpl(arg.get, arg.set);
239
+ }
240
+ var reactiveMap = /* @__PURE__ */ new WeakMap();
241
+ var readonlyMap = /* @__PURE__ */ new WeakMap();
242
+ var shallowReactiveMap = /* @__PURE__ */ new WeakMap();
243
+ function toReactive(value) {
244
+ return value !== null && typeof value === "object" ? reactive(value) : value;
245
+ }
246
+ var arrayInstrumentations = {};
247
+ ["includes", "indexOf", "lastIndexOf"].forEach((method) => {
248
+ arrayInstrumentations[method] = function(...args) {
249
+ const arr = toRaw(this);
250
+ for (let i = 0; i < this.length; i++) track(arr, i);
251
+ let res = arr[method](...args);
252
+ if (res === -1 || res === false) res = arr[method](...args.map(toRaw));
253
+ return res;
254
+ };
255
+ });
256
+ ["push", "pop", "shift", "unshift", "splice"].forEach((method) => {
257
+ arrayInstrumentations[method] = function(...args) {
258
+ pauseTracking();
259
+ const res = toRaw(this)[method].apply(this, args);
260
+ resetTracking();
261
+ return res;
262
+ };
263
+ });
264
+ function createHandler(shallow = false, readonly2 = false) {
265
+ return {
266
+ get(target, key, receiver) {
267
+ if (key === RAW) return target;
268
+ if (key === IS_REACTIVE) return !readonly2;
269
+ if (key === IS_READONLY) return readonly2;
270
+ if (key === MARK_RAW) return target[MARK_RAW];
271
+ const isArray = Array.isArray(target);
272
+ if (!readonly2 && isArray && hasOwn(arrayInstrumentations, key)) {
273
+ return Reflect.get(arrayInstrumentations, key, receiver);
274
+ }
275
+ const res = Reflect.get(target, key, receiver);
276
+ if (typeof key === "symbol" || key === "__proto__") return res;
277
+ if (!readonly2) track(target, key);
278
+ if (shallow) return res;
279
+ if (isRef(res)) return isArray ? res : res.value;
280
+ return res !== null && typeof res === "object" && !res[MARK_RAW] ? readonly2 ? readonlyProxy(res) : reactive(res) : res;
281
+ },
282
+ set(target, key, value, receiver) {
283
+ if (readonly2) {
284
+ console.warn(`[fnetro] Cannot set "${String(key)}" on readonly object`);
285
+ return true;
286
+ }
287
+ const oldVal = target[key];
288
+ const result = Reflect.set(target, key, value, receiver);
289
+ if (hasChanged(value, oldVal)) trigger(target, key, value, oldVal);
290
+ return result;
291
+ },
292
+ deleteProperty(target, key) {
293
+ if (readonly2) return true;
294
+ const hadKey = hasOwn(target, key);
295
+ const result = Reflect.deleteProperty(target, key);
296
+ if (hadKey && result) trigger(target, key);
297
+ return result;
298
+ },
299
+ has(target, key) {
300
+ const res = Reflect.has(target, key);
301
+ track(target, key);
302
+ return res;
303
+ },
304
+ ownKeys(target) {
305
+ track(target, Array.isArray(target) ? "length" : "__iterate__");
306
+ return Reflect.ownKeys(target);
307
+ }
308
+ };
309
+ }
310
+ function reactive(target) {
311
+ if (isReadonly(target)) return target;
312
+ if (target[MARK_RAW]) return target;
313
+ if (reactiveMap.has(target)) return reactiveMap.get(target);
314
+ const proxy = new Proxy(target, createHandler());
315
+ reactiveMap.set(target, proxy);
316
+ return proxy;
317
+ }
318
+ function shallowReactive(target) {
319
+ if (shallowReactiveMap.has(target)) return shallowReactiveMap.get(target);
320
+ const proxy = new Proxy(target, createHandler(true));
321
+ shallowReactiveMap.set(target, proxy);
322
+ return proxy;
323
+ }
324
+ function readonlyProxy(target) {
325
+ if (readonlyMap.has(target)) return readonlyMap.get(target);
326
+ const proxy = new Proxy(target, createHandler(false, true));
327
+ readonlyMap.set(target, proxy);
328
+ return proxy;
329
+ }
330
+ function readonly(target) {
331
+ return readonlyProxy(target);
332
+ }
333
+ function markRaw(value) {
334
+ ;
335
+ value[MARK_RAW] = true;
336
+ return value;
337
+ }
338
+ function toRaw(observed) {
339
+ const raw = observed?.[RAW];
340
+ return raw ? toRaw(raw) : observed;
341
+ }
342
+ function isReactive(value) {
343
+ if (isReadonly(value)) return isReactive(value[RAW]);
344
+ return !!(value && value[IS_REACTIVE]);
345
+ }
346
+ function isReadonly(value) {
347
+ return !!(value && value[IS_READONLY]);
348
+ }
349
+ function traverse(value, seen = /* @__PURE__ */ new Set()) {
350
+ if (!value || typeof value !== "object" || seen.has(value)) return value;
351
+ seen.add(value);
352
+ if (isRef(value)) {
353
+ traverse(value.value, seen);
354
+ return value;
355
+ }
356
+ if (Array.isArray(value)) {
357
+ value.forEach((v) => traverse(v, seen));
358
+ return value;
359
+ }
360
+ for (const key in value) traverse(value[key], seen);
361
+ return value;
362
+ }
363
+ function normalizeSource(src) {
364
+ if (Array.isArray(src)) return () => src.map((s) => isRef(s) ? s.value : s());
365
+ if (isRef(src)) return () => src.value;
366
+ return src;
367
+ }
368
+ function watch(source, cb, opts = {}) {
369
+ const getter = opts.deep ? () => traverse(normalizeSource(source)()) : normalizeSource(source);
370
+ let oldVal = void 0;
371
+ let cleanupFn;
372
+ const cleanup = (fn) => {
373
+ cleanupFn = fn;
374
+ };
375
+ const job = () => {
376
+ if (!effect2.active) return;
377
+ cleanupFn?.();
378
+ cleanupFn = void 0;
379
+ const newVal = effect2.run();
380
+ if (opts.deep || hasChanged(newVal, oldVal)) {
381
+ cb(newVal, oldVal, cleanup);
382
+ oldVal = newVal;
383
+ }
384
+ if (opts.once) effect2.stop();
385
+ };
386
+ const effect2 = new ReactiveEffect(getter, job, activeScope);
387
+ if (opts.immediate) {
388
+ cleanupFn?.();
389
+ cleanupFn = void 0;
390
+ const val = effect2.run();
391
+ cb(val, oldVal, cleanup);
392
+ oldVal = val;
393
+ } else {
394
+ oldVal = effect2.run();
395
+ }
396
+ return () => effect2.stop();
397
+ }
398
+ var __hooks = {
399
+ useValue: (r) => isRef(r) ? r.value : r(),
400
+ useLocalRef: (init) => ref(init),
401
+ useLocalReactive: (init) => reactive(init)
402
+ };
403
+ function use(source) {
404
+ return __hooks.useValue(source);
405
+ }
406
+ function useLocalRef(init) {
407
+ return __hooks.useLocalRef(init);
408
+ }
409
+ function useLocalReactive(init) {
410
+ return __hooks.useLocalReactive(init);
411
+ }
412
+ function definePage(def) {
413
+ return { __type: "page", ...def };
414
+ }
415
+ function defineGroup(def) {
416
+ return { __type: "group", ...def };
417
+ }
418
+ function defineLayout(Component) {
419
+ return { __type: "layout", Component };
420
+ }
421
+ function defineMiddleware(handler) {
422
+ return { __type: "middleware", handler };
423
+ }
424
+ function defineApiRoute(path, register) {
425
+ return { __type: "api", path, register };
426
+ }
427
+ function resolveRoutes(routes, options = {}) {
428
+ const pages = [];
429
+ const apis = [];
430
+ for (const route of routes) {
431
+ if (route.__type === "api") {
432
+ apis.push({ ...route, path: (options.prefix ?? "") + route.path });
433
+ } else if (route.__type === "group") {
434
+ const prefix = (options.prefix ?? "") + route.prefix;
435
+ const mw = [...options.middleware ?? [], ...route.middleware ?? []];
436
+ const layout = route.layout !== void 0 ? route.layout : options.layout;
437
+ const sub = resolveRoutes(route.routes, { prefix, middleware: mw, layout });
438
+ pages.push(...sub.pages);
439
+ apis.push(...sub.apis);
440
+ } else {
441
+ const fullPath = (options.prefix ?? "") + route.path;
442
+ const layout = route.layout !== void 0 ? route.layout : options.layout;
443
+ const middleware = [...options.middleware ?? [], ...route.middleware ?? []];
444
+ pages.push({ fullPath, page: route, layout, middleware });
445
+ }
446
+ }
447
+ return { pages, apis };
448
+ }
449
+ var SPA_HEADER = "x-fnetro-spa";
450
+ var STATE_KEY = "__FNETRO_STATE__";
451
+ var PARAMS_KEY = "__FNETRO_PARAMS__";
452
+ function hasChanged(a, b) {
453
+ return !Object.is(a, b);
454
+ }
455
+ function hasOwn(obj, key) {
456
+ return Object.prototype.hasOwnProperty.call(obj, key);
457
+ }
458
+ export {
459
+ EffectScope,
460
+ PARAMS_KEY,
461
+ ReactiveEffect,
462
+ SPA_HEADER,
463
+ STATE_KEY,
464
+ __hooks,
465
+ computed,
466
+ defineApiRoute,
467
+ defineGroup,
468
+ defineLayout,
469
+ defineMiddleware,
470
+ definePage,
471
+ effect,
472
+ effectScope,
473
+ getCurrentScope,
474
+ isReactive,
475
+ isReadonly,
476
+ isRef,
477
+ markRaw,
478
+ onScopeDispose,
479
+ reactive,
480
+ readonly,
481
+ ref,
482
+ resolveRoutes,
483
+ shallowReactive,
484
+ shallowRef,
485
+ toRaw,
486
+ toRef,
487
+ toRefs,
488
+ triggerRef,
489
+ unref,
490
+ use,
491
+ useLocalReactive,
492
+ useLocalRef,
493
+ watch,
494
+ watchEffect
495
+ };