fusee-framework 1.8.0 → 1.9.1
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 +64 -3
- package/app/benchmark/vite.config.js +23 -0
- package/auto-imports.d.ts +4 -0
- package/bin/create-fusee-linux +0 -0
- package/bin/create-fusee-mac-arm64 +0 -0
- package/bin/create-fusee-mac-intel +0 -0
- package/bin/create-fusee-win.exe +0 -0
- package/bin/create-fusee.exe +0 -0
- package/create-fusee-go/internal/assets/embed/framework/auto-import-preset.js +15 -9
- package/create-fusee-go/internal/assets/embed/framework/core/async-context.js +27 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/ast.js +167 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/errors-list.js +47 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/errors.js +107 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/generator.js +363 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/lexer.js +347 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/main-compiler.js +115 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/parser.js +414 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/plugins/actions-plugin.js +263 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/plugins/compiler-plugin.d.ts +5 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/plugins/compiler-plugin.js +45 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/plugins/file-router-plugin.js +301 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/plugins/router-plugin.js +196 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler/transformer.js +398 -0
- package/create-fusee-go/internal/assets/embed/framework/core/component.js +61 -23
- package/create-fusee-go/internal/assets/embed/framework/core/di.js +187 -0
- package/create-fusee-go/internal/assets/embed/framework/core/directives.js +40 -96
- package/create-fusee-go/internal/assets/embed/framework/core/evaluator.js +1 -1
- package/create-fusee-go/internal/assets/embed/framework/core/h.js +430 -0
- package/create-fusee-go/internal/assets/embed/framework/core/hydration.js +83 -0
- package/create-fusee-go/internal/assets/embed/framework/core/reconcile.js +151 -0
- package/create-fusee-go/internal/assets/embed/framework/core/signal.js +269 -0
- package/create-fusee-go/internal/assets/embed/framework/core/store.js +322 -81
- package/create-fusee-go/internal/assets/embed/framework/index.js +5 -3
- package/create-fusee-go/internal/assets/embed/framework/router/file-router.js +1 -1
- package/create-fusee-go/internal/assets/embed/framework/router/router.js +113 -21
- package/create-fusee-go/internal/assets/embed/framework/server/actions.js +173 -0
- package/create-fusee-go/internal/assets/embed/framework/server/actions.server.js +88 -0
- package/create-fusee-go/internal/assets/embed/framework/server/index.js +18 -0
- package/create-fusee-go/internal/assets/embed/framework/types/actions.d.ts +50 -0
- package/create-fusee-go/internal/assets/embed/framework/types/actions.server.d.ts +36 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/ast.d.ts +166 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/errors-codes.d.ts +23 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/errors.d.ts +43 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/generator.d.ts +8 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/h.d.ts +46 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/lexer.d.ts +27 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/main-compiler.d.ts +60 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/parser.d.ts +4 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/plugins/actions.d.ts +30 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/plugins/compiler-plugin.d.ts +5 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/plugins/file-router-plugins.d.ts +32 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/plugins/router-plugin.d.ts +24 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler/transformer.d.ts +28 -0
- package/create-fusee-go/internal/assets/embed/framework/types/component.d.ts +89 -88
- package/create-fusee-go/internal/assets/embed/framework/types/di.d.ts +43 -0
- package/create-fusee-go/internal/assets/embed/framework/types/hydration.d.ts +30 -0
- package/create-fusee-go/internal/assets/embed/framework/types/index.d.ts +38 -22
- package/create-fusee-go/internal/assets/embed/framework/types/reconcile.d.ts +7 -0
- package/create-fusee-go/internal/assets/embed/framework/types/router.d.ts +11 -1
- package/create-fusee-go/internal/assets/embed/framework/types/server.d.ts +11 -0
- package/create-fusee-go/internal/assets/embed/framework/types/signal.d.ts +142 -79
- package/create-fusee-go/internal/assets/embed/framework/types/store.d.ts +66 -8
- package/framework/auto-import-preset.js +3 -1
- package/framework/core/async-context.js +27 -0
- package/framework/core/compiler/ast.js +167 -0
- package/framework/core/compiler/errors-list.js +47 -0
- package/framework/core/compiler/errors.js +107 -0
- package/framework/core/compiler/generator.js +363 -0
- package/framework/core/compiler/lexer.js +347 -0
- package/framework/core/compiler/main-compiler.js +115 -0
- package/framework/core/compiler/parser.js +414 -0
- package/framework/core/compiler/plugins/actions-plugin.js +263 -0
- package/framework/core/compiler/plugins/compiler-plugin.d.ts +5 -0
- package/framework/core/compiler/plugins/compiler-plugin.js +45 -0
- package/framework/core/compiler/plugins/file-router-plugin.js +301 -0
- package/framework/core/compiler/plugins/router-plugin.js +196 -0
- package/framework/core/compiler/transformer.js +398 -0
- package/framework/core/component.js +34 -10
- package/framework/core/evaluator.js +1 -1
- package/framework/core/h.js +430 -0
- package/framework/core/hydration.js +83 -0
- package/framework/core/signal.js +17 -15
- package/framework/server/actions.js +173 -0
- package/framework/server/actions.server.js +88 -0
- package/framework/server/index.js +18 -0
- package/framework/types/actions.d.ts +50 -0
- package/framework/types/actions.server.d.ts +36 -0
- package/framework/types/compiler/ast.d.ts +166 -0
- package/framework/types/compiler/errors-codes.d.ts +23 -0
- package/framework/types/compiler/errors.d.ts +43 -0
- package/framework/types/compiler/generator.d.ts +8 -0
- package/framework/types/compiler/h.d.ts +46 -0
- package/framework/types/compiler/lexer.d.ts +27 -0
- package/framework/types/compiler/main-compiler.d.ts +60 -0
- package/framework/types/compiler/parser.d.ts +4 -0
- package/framework/types/compiler/plugins/actions.d.ts +30 -0
- package/framework/types/compiler/plugins/compiler-plugin.d.ts +5 -0
- package/framework/types/compiler/plugins/file-router-plugins.d.ts +32 -0
- package/framework/types/compiler/plugins/router-plugin.d.ts +24 -0
- package/framework/types/compiler/transformer.d.ts +28 -0
- package/framework/types/hydration.d.ts +30 -0
- package/framework/types/index.d.ts +6 -0
- package/framework/types/server.d.ts +11 -0
- package/framework/types/signal.d.ts +2 -7
- package/ghid_go_fusee_integrat_go1_26.txt +276 -0
- package/ghid_rust_fusee_rust_1_95_0.txt +1118 -0
- package/package.json +44 -36
- package/vite.config.js +65 -53
- package/create-fusee-go/internal/assets/embed/framework/bin/create-fusee.js +0 -199
|
@@ -1,8 +1,66 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
+
}
|
|
@@ -8,6 +8,8 @@ export const FuseePreset = {
|
|
|
8
8
|
'defineStore', 'resetStore', 'clearStores',
|
|
9
9
|
'registerStorePlugin', 'useNestedStore',
|
|
10
10
|
'storeToRefs', 'storeToState', 'storeToGetters',
|
|
11
|
-
'MutationType'
|
|
11
|
+
'MutationType',
|
|
12
|
+
'provide', 'inject', 'provideGlobal', 'InjectionToken',
|
|
13
|
+
'defineComposable', 'assertSetupContext'
|
|
12
14
|
]
|
|
13
15
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
let _als = null
|
|
2
|
+
|
|
3
|
+
export function _registerALS(als) {
|
|
4
|
+
_als = als
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function _getALS() {
|
|
8
|
+
return _als
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const _globalInFlightMaps = {
|
|
12
|
+
byKey: new Map(),
|
|
13
|
+
byFetcher: new WeakMap()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getInFlightStore() {
|
|
17
|
+
if (_als) {
|
|
18
|
+
const ctx = _als.getStore()
|
|
19
|
+
if (ctx) return ctx.inFlightMaps
|
|
20
|
+
}
|
|
21
|
+
return _globalInFlightMaps
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isSSRContext() {
|
|
25
|
+
if (!_als) return false
|
|
26
|
+
return _als.getStore() !== undefined
|
|
27
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
export const NodeType = {
|
|
2
|
+
ROOT: 'Root',
|
|
3
|
+
ELEMENT: 'Element',
|
|
4
|
+
COMPONENT: 'Component',
|
|
5
|
+
TEXT: 'Text',
|
|
6
|
+
INTERPOLATION: 'Interpolation',
|
|
7
|
+
EXPRESSION: 'Expression',
|
|
8
|
+
ATTRIBUTE: 'Attribute',
|
|
9
|
+
BINDING: 'Binding',
|
|
10
|
+
EVENT: 'Event',
|
|
11
|
+
DIRECTIVE: 'Directive',
|
|
12
|
+
SLOT_OUTLET: 'SlotOutlet',
|
|
13
|
+
SLOT_CONTENT: 'SlotContent'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createLoc(start, end, source) {
|
|
17
|
+
return { start, end, source }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createPos(line, col, offset) {
|
|
21
|
+
return { line, col, offset }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createRoot(children = [], loc = null) {
|
|
25
|
+
return { type: NodeType.ROOT, children, loc }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createElement(tag, props = [], children = [], selfClosing = false, loc = null) {
|
|
29
|
+
return {
|
|
30
|
+
type: NodeType.ELEMENT,
|
|
31
|
+
tag,
|
|
32
|
+
props,
|
|
33
|
+
children,
|
|
34
|
+
selfClosing,
|
|
35
|
+
isStatic: false,
|
|
36
|
+
hoisted: false,
|
|
37
|
+
loc
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createComponent(name, props = [], slots = {}, loc = null) {
|
|
42
|
+
return {
|
|
43
|
+
type: NodeType.COMPONENT,
|
|
44
|
+
name,
|
|
45
|
+
props,
|
|
46
|
+
slots,
|
|
47
|
+
loc
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createText(content, loc = null) {
|
|
52
|
+
return { type: NodeType.TEXT, content, loc }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function createInterpolation(expression, loc = null) {
|
|
56
|
+
return {
|
|
57
|
+
type: NodeType.INTERPOLATION,
|
|
58
|
+
expression,
|
|
59
|
+
loc
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function createExpression(content, isStatic = false, loc = null) {
|
|
64
|
+
return {
|
|
65
|
+
type: NodeType.EXPRESSION,
|
|
66
|
+
content,
|
|
67
|
+
isStatic,
|
|
68
|
+
loc
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createAttribute(name, value, loc = null) {
|
|
73
|
+
return {
|
|
74
|
+
type: NodeType.ATTRIBUTE,
|
|
75
|
+
name,
|
|
76
|
+
value,
|
|
77
|
+
loc
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createBinding(name, expression, isProp = false, loc = null) {
|
|
82
|
+
return {
|
|
83
|
+
type: NodeType.BINDING,
|
|
84
|
+
name,
|
|
85
|
+
expression,
|
|
86
|
+
isProp,
|
|
87
|
+
loc
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function createEvent(name, expression, modifiers = [], loc = null) {
|
|
92
|
+
return {
|
|
93
|
+
type: NodeType.EVENT,
|
|
94
|
+
name,
|
|
95
|
+
expression,
|
|
96
|
+
modifiers,
|
|
97
|
+
loc
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function createDirective(name, expression = null, arg = null, loc = null) {
|
|
102
|
+
return {
|
|
103
|
+
type: NodeType.DIRECTIVE,
|
|
104
|
+
name,
|
|
105
|
+
expression,
|
|
106
|
+
arg,
|
|
107
|
+
loc
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function createSlotOutlet(slotName = 'default', fallback = [], loc = null) {
|
|
112
|
+
return {
|
|
113
|
+
type: NodeType.SLOT_OUTLET,
|
|
114
|
+
slotName,
|
|
115
|
+
fallback,
|
|
116
|
+
loc
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function createSlotContent(slotName = 'default', children = [], loc = null) {
|
|
121
|
+
return {
|
|
122
|
+
type: NodeType.SLOT_CONTENT,
|
|
123
|
+
slotName,
|
|
124
|
+
children,
|
|
125
|
+
loc
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function createForArg(item, source, index = null, loc = null) {
|
|
130
|
+
return { item, source, index, loc }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function isElement(node) {
|
|
134
|
+
return node?.type === NodeType.ELEMENT
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function isComponent(node) {
|
|
138
|
+
return node?.type === NodeType.COMPONENT
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function isText(node) {
|
|
142
|
+
return node?.type === NodeType.TEXT
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function isInterpolation(node) {
|
|
146
|
+
return node?.type === NodeType.INTERPOLATION
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function isDirective(node, name) {
|
|
150
|
+
return node?.type === NodeType.DIRECTIVE && (name == null || node.name === name)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function isStaticText(node) {
|
|
154
|
+
return node?.type === NodeType.TEXT || (node?.type === NodeType.INTERPOLATION && node.expression?.isStatic)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function findDirective(element, name) {
|
|
158
|
+
return element.props.find(p => isDirective(p, name)) ?? null
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function getEvents(element) {
|
|
162
|
+
return element.props.filter(p => p.type === NodeType.EVENT)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function cloneNode(node) {
|
|
166
|
+
return { ...node, props: node.props ? [...node.props] : undefined, children: node.children ? [...node.children] : undefined }
|
|
167
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const ErrorCode = {
|
|
2
|
+
UNEXPECTED_CHAR: 'E001',
|
|
3
|
+
UNTERMINATED_STRING: 'E002',
|
|
4
|
+
UNTERMINATED_MUSTACHE: 'E003',
|
|
5
|
+
UNTERMINATED_TAG: 'E004',
|
|
6
|
+
MALFORMED_COMMENT: 'E005',
|
|
7
|
+
UNEXPECTED_TOKEN: 'P001',
|
|
8
|
+
MISSING_CLOSING_TAG: 'P002',
|
|
9
|
+
UNEXPECTED_CLOSING_TAG: 'P003',
|
|
10
|
+
INVALID_DIRECTIVE_SYNTAX: 'P004',
|
|
11
|
+
INVALID_FOR_SYNTAX: 'P005',
|
|
12
|
+
DUPLICATE_KEY: 'P006',
|
|
13
|
+
V_ELSE_NO_IF: 'P007',
|
|
14
|
+
EMPTY_EXPRESSION: 'P008',
|
|
15
|
+
INVALID_SLOT_NAME: 'P009',
|
|
16
|
+
DUPLICATE_DIRECTIVE: 'T001',
|
|
17
|
+
FOR_MISSING_KEY: 'T002',
|
|
18
|
+
MODEL_ON_NON_INPUT: 'T003',
|
|
19
|
+
COMPONENT_NOT_REGISTERED: 'T004',
|
|
20
|
+
UNKNOWN_IDENTIFIER: 'S001',
|
|
21
|
+
STATIC_FOR_KEY: 'S002',
|
|
22
|
+
UNKNOWN_NODE_TYPE: 'G001',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const ERROR_MESSAGES = {
|
|
26
|
+
[ErrorCode.UNEXPECTED_CHAR]: 'Unexpected character "{0}"',
|
|
27
|
+
[ErrorCode.UNTERMINATED_STRING]: 'Unterminated string literal',
|
|
28
|
+
[ErrorCode.UNTERMINATED_MUSTACHE]: 'Unterminated mustache expression "{0}"',
|
|
29
|
+
[ErrorCode.UNTERMINATED_TAG]: 'Unterminated tag "<{0}"',
|
|
30
|
+
[ErrorCode.MALFORMED_COMMENT]: 'Malformed HTML comment',
|
|
31
|
+
[ErrorCode.UNEXPECTED_TOKEN]: 'Unexpected token "{0}", expected "{1}"',
|
|
32
|
+
[ErrorCode.MISSING_CLOSING_TAG]: 'Missing closing tag for <{0}>',
|
|
33
|
+
[ErrorCode.UNEXPECTED_CLOSING_TAG]: 'Unexpected closing tag </{0}>',
|
|
34
|
+
[ErrorCode.INVALID_DIRECTIVE_SYNTAX]: 'Invalid directive syntax: "{0}"',
|
|
35
|
+
[ErrorCode.INVALID_FOR_SYNTAX]: 'Invalid f-for syntax: "{0}". Expected "(item, index) in source" or "item in source"',
|
|
36
|
+
[ErrorCode.DUPLICATE_KEY]: 'Duplicate attribute "{0}" on element <{1}>',
|
|
37
|
+
[ErrorCode.V_ELSE_NO_IF]: 'f-else / f-else-if has no matching f-if',
|
|
38
|
+
[ErrorCode.EMPTY_EXPRESSION]: 'Expression in "{0}" must not be empty',
|
|
39
|
+
[ErrorCode.INVALID_SLOT_NAME]: 'Invalid slot name "{0}"',
|
|
40
|
+
[ErrorCode.DUPLICATE_DIRECTIVE]: 'Duplicate directive "f-{0}" on element <{1}>',
|
|
41
|
+
[ErrorCode.FOR_MISSING_KEY]: 'f-for on <{0}> is missing a :key binding — add :key="<unique expr>"',
|
|
42
|
+
[ErrorCode.MODEL_ON_NON_INPUT]: 'f-model can only be used on <input>, <textarea> or <select>, got <{0}>',
|
|
43
|
+
[ErrorCode.COMPONENT_NOT_REGISTERED]: 'Component "{0}" is used in the template but not registered',
|
|
44
|
+
[ErrorCode.UNKNOWN_NODE_TYPE]: 'Unknown AST node type "{0}" encountered in generator',
|
|
45
|
+
[ErrorCode.UNKNOWN_IDENTIFIER]: 'Unknown identifier "{0}" in expression "{1}" — not found in component scope',
|
|
46
|
+
[ErrorCode.STATIC_FOR_KEY]: ':key="{0}" is a static literal — keys must be unique per item (use a dynamic expression like :key="item.id")',
|
|
47
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ErrorCode, ERROR_MESSAGES } from './errors-list.js'
|
|
2
|
+
|
|
3
|
+
export class CompileError extends Error {
|
|
4
|
+
constructor(code, loc, source, ...args) {
|
|
5
|
+
const template = ERROR_MESSAGES[code] ?? `Unknown compiler error (${code})`
|
|
6
|
+
const message = _interpolate(template, args)
|
|
7
|
+
super(message)
|
|
8
|
+
this.name = 'CompileError'
|
|
9
|
+
this.code = code
|
|
10
|
+
this.loc = loc
|
|
11
|
+
this.source = source
|
|
12
|
+
this._snippet = null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
format(filePath = '<template>') {
|
|
16
|
+
const { line, col } = this.loc?.start ?? { line: '?', col: '?' }
|
|
17
|
+
const header = `[fusée] ${this.name} ${this.code} at ${filePath}:${line}:${col}`
|
|
18
|
+
const snippet = this._buildSnippet()
|
|
19
|
+
return snippet ? `${header}\n${this.message}\n\n${snippet}` : `${header}\n${this.message}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_buildSnippet() {
|
|
23
|
+
if (this._snippet !== null) return this._snippet
|
|
24
|
+
if (!this.source || !this.loc?.start) {
|
|
25
|
+
this._snippet = ''
|
|
26
|
+
return ''
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const lines = this.source.split('\n')
|
|
30
|
+
const lineIdx = this.loc.start.line - 1
|
|
31
|
+
const col = this.loc.start.col
|
|
32
|
+
const CONTEXT = 2
|
|
33
|
+
const firstLine = Math.max(0, lineIdx - CONTEXT)
|
|
34
|
+
const lastLine = Math.min(lines.length - 1, lineIdx + CONTEXT)
|
|
35
|
+
const width = String(lastLine + 1).length
|
|
36
|
+
const parts = []
|
|
37
|
+
|
|
38
|
+
for (let i = firstLine; i <= lastLine; i++) {
|
|
39
|
+
const lineNo = String(i + 1).padStart(width, ' ')
|
|
40
|
+
const prefix = i === lineIdx ? '> ' : ' '
|
|
41
|
+
parts.push(`${prefix}${lineNo} | ${lines[i]}`)
|
|
42
|
+
if (i === lineIdx) {
|
|
43
|
+
const caretPad = ' '.repeat(width + 4 + (col - 1))
|
|
44
|
+
const caretLen = Math.max(1, (this.loc.end?.col ?? col) - col)
|
|
45
|
+
parts.push(`${caretPad}${'~'.repeat(caretLen)}`)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this._snippet = parts.join('\n')
|
|
50
|
+
return this._snippet
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class CompileWarning {
|
|
55
|
+
constructor(code, loc, source, ...args) {
|
|
56
|
+
const template = ERROR_MESSAGES[code] ?? `Unknown compiler warning (${code})`
|
|
57
|
+
this.message = _interpolate(template, args)
|
|
58
|
+
this.code = code
|
|
59
|
+
this.loc = loc
|
|
60
|
+
this.source = source
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
format(filePath = '<template>') {
|
|
64
|
+
const { line, col } = this.loc?.start ?? { line: '?', col: '?' }
|
|
65
|
+
return `[fusée] Warning ${this.code} at ${filePath}:${line}:${col}\n${this.message}`
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class ErrorCollector {
|
|
70
|
+
constructor(source) {
|
|
71
|
+
this.source = source
|
|
72
|
+
this.errors = []
|
|
73
|
+
this.warnings = []
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
error(code, loc, ...args) {
|
|
77
|
+
const err = new CompileError(code, loc, this.source, ...args)
|
|
78
|
+
this.errors.push(err)
|
|
79
|
+
return err
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
warn(code, loc, ...args) {
|
|
83
|
+
const w = new CompileWarning(code, loc, this.source, ...args)
|
|
84
|
+
this.warnings.push(w)
|
|
85
|
+
return w
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
throwIfAny() {
|
|
89
|
+
if (this.errors.length > 0) throw this.errors[0]
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get hasErrors() {
|
|
93
|
+
return this.errors.length > 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get hasWarnings() {
|
|
97
|
+
return this.warnings.length > 0
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function _interpolate(template, args) {
|
|
102
|
+
return template.replace(/\{(\d+)\}/g, (_, i) => args[i] ?? '')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function throwError(code, loc, source, ...args) {
|
|
106
|
+
throw new CompileError(code, loc, source, ...args)
|
|
107
|
+
}
|