fusee-framework 1.7.0 → 1.8.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.
Files changed (38) hide show
  1. package/README.md +145 -139
  2. package/app/benchmark/benchmark.js +2 -2
  3. package/app/main.js +24 -3
  4. package/app/main.ts +7 -1
  5. package/app/pages/_layout.js +27 -0
  6. package/app/pages/async-work.js +65 -0
  7. package/app/pages/index.js +25 -5
  8. package/app/pages/index.ts +9 -0
  9. package/app/pages/router-example.js +24 -1
  10. package/app/pages/scroll-demo.ts +102 -0
  11. package/app/providers/ChildComponent.js +8 -2
  12. package/app/providers/ChildComponent.ts +47 -47
  13. package/app/providers/GrandchildComponent.js +19 -0
  14. package/app/providers/ParentComponent.js +5 -1
  15. package/app/routes/RouterExample.js +23 -1
  16. package/app/routes/TestResource.js +47 -0
  17. package/app/services.js +15 -0
  18. package/auto-imports.d.ts +8 -0
  19. package/framework/auto-import-preset.js +13 -9
  20. package/framework/core/component.js +27 -13
  21. package/framework/core/di.js +187 -0
  22. package/framework/core/directives.js +40 -96
  23. package/framework/core/evaluator.js +1 -1
  24. package/framework/core/reconcile.js +151 -0
  25. package/framework/core/signal.js +267 -0
  26. package/framework/core/store.js +322 -81
  27. package/framework/index.js +5 -3
  28. package/framework/router/file-router.js +1 -1
  29. package/framework/router/router.js +113 -21
  30. package/framework/types/component.d.ts +89 -88
  31. package/framework/types/di.d.ts +43 -0
  32. package/framework/types/index.d.ts +32 -22
  33. package/framework/types/reconcile.d.ts +7 -0
  34. package/framework/types/router.d.ts +11 -1
  35. package/framework/types/signal.d.ts +147 -79
  36. package/framework/types/store.d.ts +66 -8
  37. package/package.json +1 -1
  38. package/vite.config.js +7 -1
@@ -1,79 +1,147 @@
1
- export type SignalAccessor<T> = {
2
- (): T;
3
- (newValue: T): void;
4
- isSignal: boolean;
5
- }
6
-
7
- export interface ReactiveArrayMethods<T> {
8
- map<U>(callbackfn: (value: T, index: number, array: T[]) => U): Computed<U[]>;
9
- filter(predicate: (value: T, index: number, array: T[]) => boolean): Computed<T[]>;
10
- slice(start?: number, end?: number): Computed<T[]>;
11
- reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): Computed<U>;
12
- reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): Computed<T>;
13
- find(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<T | undefined>;
14
- findLast(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<T | undefined>;
15
- findIndex(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<number>;
16
- findLastIndex(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<number>;
17
- every(predicate: (value: T, index: number, array: T[]) => boolean): Computed<boolean>;
18
- some(predicate: (value: T, index: number, array: T[]) => boolean): Computed<boolean>;
19
- includes(searchElement: T, fromIndex?: number): Computed<boolean>;
20
- indexOf(searchElement: T, fromIndex?: number): Computed<number>;
21
- lastIndexOf(searchElement: T, fromIndex?: number): Computed<number>;
22
- at(index: number): Computed<T | undefined>;
23
- concat(...items: (T | T[])[]): Computed<T[]>;
24
- flat<depth extends number = 1>(depth?: depth): Computed<any[]>;
25
- flatMap<U>(callback: (value: T, index: number, array: T[]) => U | U[]): Computed<U[]>;
26
- join(separator?: string): Computed<string>;
27
- }
28
-
29
- export type ArraySignalAccessor<T extends any[]> = SignalAccessor<T> & ReactiveArrayMethods<T[number]> & {
30
- push(...items: T[number][]): number;
31
- pop(): T[number] | undefined;
32
- shift(): T[number] | undefined;
33
- unshift(...items: T[number][]): number;
34
- splice(start: number, deleteCount: number, ...items: T[number][]): T[number][];
35
- remove(predicate: (item: T[number], index: number) => boolean): void;
36
- clear(): void;
37
- sort(compareFn?: (a: T[number], b: T[number]) => number): ArraySignalAccessor<T>;
38
- reverse(): ArraySignalAccessor<T>;
39
- }
40
-
41
- export type ComputedAccessor<T> = {
42
- (): T;
43
- isSignal: boolean;
44
- readonly: true;
45
- } & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
46
-
47
- export type Signal<T = any> = SignalAccessor<T> & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
48
- export type Computed<T = any> = ComputedAccessor<T> & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
49
-
50
- type EffectRunner = {
51
- (): void;
52
- deps: Set<Set<EffectRunner>>;
53
- }
54
-
55
- export type WatchSource<T = any> = (() => T) | Signal<T> | Computed<T>
56
- export type WatchCallback<T = any> = (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void
57
-
58
- export interface WatchOptions {
59
- immediate?: boolean;
60
- equals?: (a: any, b: any) => boolean;
61
- }
62
-
63
- export declare function signal<T extends any[]>(initialValue: T): ArraySignalAccessor<T>
64
- export declare function signal<T>(initialValue: T): SignalAccessor<T>
65
- export declare function effect(fn: () => void): () => void
66
- export declare function computed<T>(fn: () => T): Computed<T>
67
- export declare function batch<T>(fn: () => T): T
68
- export declare function untrack<T>(fn: () => T): T
69
- export declare function watch<T>(source: WatchSource<T>, callback: WatchCallback<T>, options?: WatchOptions): () => void
70
- export declare function watch<T extends any[]>(
71
- sources: [...{ [K in keyof T]: WatchSource<T[K]> }],
72
- callback: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void,
73
- options?: WatchOptions
74
- ): () => void
75
- export declare function inspect(...args: any[]): (() => void) | void
76
- export declare function onCleanup(fn: () => void): void
77
-
78
- declare function setEffectHook(fn: (eff: any) => void): void
79
-
1
+ export type SignalAccessor<T> = {
2
+ (): T;
3
+ (newValue: T): void;
4
+ isSignal: boolean;
5
+ }
6
+
7
+ export interface ReactiveArrayMethods<T> {
8
+ map<U>(callbackfn: (value: T, index: number, array: T[]) => U): Computed<U[]>;
9
+ filter(predicate: (value: T, index: number, array: T[]) => boolean): Computed<T[]>;
10
+ slice(start?: number, end?: number): Computed<T[]>;
11
+ reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): Computed<U>;
12
+ reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): Computed<T>;
13
+ find(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<T | undefined>;
14
+ findLast(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<T | undefined>;
15
+ findIndex(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<number>;
16
+ findLastIndex(predicate: (value: T, index: number, obj: T[]) => boolean): Computed<number>;
17
+ every(predicate: (value: T, index: number, array: T[]) => boolean): Computed<boolean>;
18
+ some(predicate: (value: T, index: number, array: T[]) => boolean): Computed<boolean>;
19
+ includes(searchElement: T, fromIndex?: number): Computed<boolean>;
20
+ indexOf(searchElement: T, fromIndex?: number): Computed<number>;
21
+ lastIndexOf(searchElement: T, fromIndex?: number): Computed<number>;
22
+ at(index: number): Computed<T | undefined>;
23
+ concat(...items: (T | T[])[]): Computed<T[]>;
24
+ flat<depth extends number = 1>(depth?: depth): Computed<any[]>;
25
+ flatMap<U>(callback: (value: T, index: number, array: T[]) => U | U[]): Computed<U[]>;
26
+ join(separator?: string): Computed<string>;
27
+ }
28
+
29
+ export type ArraySignalAccessor<T extends any[]> = SignalAccessor<T> & ReactiveArrayMethods<T[number]> & {
30
+ push(...items: T[number][]): number;
31
+ pop(): T[number] | undefined;
32
+ shift(): T[number] | undefined;
33
+ unshift(...items: T[number][]): number;
34
+ splice(start: number, deleteCount: number, ...items: T[number][]): T[number][];
35
+ remove(predicate: (item: T[number], index: number) => boolean): void;
36
+ clear(): void;
37
+ sort(compareFn?: (a: T[number], b: T[number]) => number): ArraySignalAccessor<T>;
38
+ reverse(): ArraySignalAccessor<T>;
39
+ }
40
+
41
+ export type ComputedAccessor<T> = {
42
+ (): T;
43
+ isSignal: boolean;
44
+ readonly: true;
45
+ } & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
46
+
47
+ export type Signal<T = any> = SignalAccessor<T> & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
48
+ export type Computed<T = any> = ComputedAccessor<T> & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
49
+
50
+ type EffectRunner = {
51
+ (): void;
52
+ deps: Set<Set<EffectRunner>>;
53
+ }
54
+
55
+ export type WatchSource<T = any> = (() => T) | Signal<T> | Computed<T>
56
+ export type WatchCallback<T = any> = (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void
57
+
58
+ export interface WatchOptions {
59
+ immediate?: boolean;
60
+ equals?: (a: any, b: any) => boolean;
61
+ }
62
+
63
+ export interface ResourceOptions {
64
+ staleTime?: number;
65
+ key?: string | number;
66
+ }
67
+
68
+ export type ResourceAccessor<T> = {
69
+ (): T | undefined;
70
+ read(): T;
71
+ isSignal: boolean;
72
+ loading: Signal<boolean>;
73
+ isFetching: Signal<boolean>;
74
+ error: Signal<any>;
75
+ } & (T extends any[] ? ReactiveArrayMethods<T[number]> : {})
76
+
77
+ export type ResourceActions<T> = {
78
+ mutate: (val: T) => void;
79
+ refetch: () => void;
80
+ }
81
+
82
+ export type ResourceReturn<T, R = unknown> = [
83
+ ResourceAccessor<T>,
84
+ {
85
+ mutate: (val: T) => void;
86
+ refetch: () => void;
87
+ }
88
+ ];
89
+
90
+ export interface SuspenseOptions {
91
+ onError?: (err: any) => void;
92
+ }
93
+
94
+ export interface SuspenseSignal<T> {
95
+ (): T;
96
+ pending: Signal<boolean>;
97
+ error: Signal<any>;
98
+ }
99
+
100
+ export type Resource<T> = [ResourceAccessor<T>, ResourceActions<T>]
101
+
102
+ export declare function signal<T extends any[]>(initialValue: T): ArraySignalAccessor<T>
103
+ export declare function signal<T>(initialValue: T): SignalAccessor<T>
104
+ export declare function effect(fn: () => void): () => void
105
+ export declare function computed<T>(fn: () => T): Computed<T>
106
+ export declare function batch<T>(fn: () => T): T
107
+ export declare function untrack<T>(fn: () => T): T
108
+ export declare function watch<T>(source: WatchSource<T>, callback: WatchCallback<T>, options?: WatchOptions): () => void
109
+ export declare function watch<T extends any[]>(
110
+ sources: [...{ [K in keyof T]: WatchSource<T[K]> }],
111
+ callback: (newValue: T, oldValue: T | undefined, onCleanup: (fn: () => void) => void) => void,
112
+ options?: WatchOptions
113
+ ): () => void
114
+ export declare function inspect(...args: any[]): (() => void) | void
115
+ export declare function onCleanup(fn: () => void): void
116
+
117
+ export function resource<T, R = any>(
118
+ fetcher: (input: R) => Promise<T>,
119
+ options?: { key?: string | number; staleTime?: number }
120
+ ): ResourceReturn<T, R>;
121
+
122
+ export function resource<T, R>(
123
+ source: () => R,
124
+ fetcher: (input: R) => Promise<T>,
125
+ options?: { key?: string | number; staleTime?: number }
126
+ ): ResourceReturn<T, R>;
127
+
128
+ export function createSuspense<T>(
129
+ renderFn: () => T,
130
+ fallbackFn: (() => T) | T,
131
+ options?: SuspenseOptions
132
+ ): [SuspenseSignal<T>, () => void];
133
+
134
+ declare function setEffectHook(fn: (eff: any) => void): void
135
+
136
+ export type AsyncPriority = 'high' | 'low';
137
+ export interface AsyncJobOptions {
138
+ priority?: AsyncPriority;
139
+ }
140
+
141
+ export function scheduleAsyncJob(fn: () => void, opts?: AsyncJobOptions): void;
142
+
143
+ export interface ResourceOptions<T = any> {
144
+ key?: string | number;
145
+ staleTime?: number;
146
+ fetchPriority?: AsyncPriority;
147
+ }
@@ -1,8 +1,66 @@
1
- export function defineStore<T>(id: string, setup: () => T): () => T;
2
- export function resetStore(id: string): void;
3
- export function clearStores(): void;
4
- export function registerStorePlugin(plugin: (store: any, id: string) => void): void;
5
-
6
- declare global {
7
- function defineStore<T>(id: string, setup: () => T): () => T;
8
- }
1
+ export type MutationType = 'direct' | 'patch object' | 'patch function';
2
+
3
+ export const MutationType: {
4
+ readonly DIRECT: 'direct';
5
+ readonly PATCH_OBJECT: 'patch object';
6
+ readonly PATCH_FUNCTION: 'patch function';
7
+ };
8
+
9
+ export interface StoreMutation {
10
+ type: MutationType;
11
+ storeId: string;
12
+ payload?: Record<string, any>;
13
+ }
14
+
15
+ export interface SubscribeOptions {
16
+ flush?: 'pre' | 'post' | 'sync';
17
+ detached?: boolean;
18
+ }
19
+
20
+ export type SubscribeCallback = (mutation: StoreMutation, state: any) => void;
21
+ export type UnsubscribeFunction = () => void;
22
+
23
+ export interface Store<T> {
24
+ readonly id: string;
25
+ readonly type: 'store';
26
+ patch(partial: Partial<{ [K in keyof T]: T[K] extends (...args: any[]) => any ? ReturnType<T[K]> : T[K] }> | ((state: T) => void)): void;
27
+ subscribe(callback: SubscribeCallback, options?: SubscribeOptions): UnsubscribeFunction;
28
+ }
29
+
30
+ export type StoreHook<T> = (() => T & Store<T>) & { $id: string };
31
+
32
+ export function defineStore<T>(id: string, setup: () => T): StoreHook<T>;
33
+ export function resetStore(id: string): void;
34
+ export function clearStores(): void;
35
+ export function registerStorePlugin(plugin: (store: any, id: string) => void): void;
36
+ export function useNestedStore<T>(useStoreFn: StoreHook<T>): T & Store<T>;
37
+
38
+ export type StoreToRefs<T> = {
39
+ [K in keyof T]: T[K] extends (...args: any[]) => infer R ? import('./signal').SignalAccessor<R> : never
40
+ }
41
+
42
+ export type StoreToState<T> = {
43
+ [K in keyof T]: T[K] extends (...args: any[]) => infer R
44
+ ? import('./signal').SignalAccessor<R> extends { readonly: true }
45
+ ? never
46
+ : import('./signal').SignalAccessor<R>
47
+ : never
48
+ }
49
+
50
+ export type StoreToGetters<T> = {
51
+ [K in keyof T]: T[K] extends (...args: any[]) => infer R
52
+ ? import('./signal').SignalAccessor<R> extends { readonly: true }
53
+ ? import('./signal').SignalAccessor<R>
54
+ : never
55
+ : never
56
+ }
57
+
58
+ export function storeToRefs<T>(store: T & Store<T>): StoreToRefs<T>;
59
+ export function storeToState<T>(store: T & Store<T>): StoreToState<T>;
60
+ export function storeToGetters<T>(store: T & Store<T>): StoreToGetters<T>;
61
+
62
+ declare global {
63
+ function defineStore<T>(id: string, setup: () => T): import('./store').StoreHook<T>;
64
+ function useNestedStore<T>(useStoreFn: import('./store').StoreHook<T>): T & Store<T>;
65
+ type MutationType = import('./store').MutationType;
66
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fusee-framework",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Fusée - Signals-first JS Framework | Peak Performance",
5
5
  "main": "framework/index.js",
6
6
  "types": "framework/types/index.d.ts",
package/vite.config.js CHANGED
@@ -39,9 +39,15 @@ export default defineConfig({
39
39
  test: {
40
40
  environment: 'jsdom',
41
41
  globals: true,
42
+ exclude: [
43
+ 'node_modules/**',
44
+ 'bench-node-1/**',
45
+ 'create-fusee-go/**',
46
+ 'dist/**'
47
+ ],
42
48
  typecheck: {
43
49
  enabled: true,
44
- include: ['**/*.test-d.ts'],
50
+ include: ['framework/**/*.test-d.ts'],
45
51
  }
46
52
  }
47
53
  })