fusee-framework 1.7.0 → 1.9.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 (77) hide show
  1. package/README.md +206 -139
  2. package/app/benchmark/benchmark.js +2 -2
  3. package/app/benchmark/vite.config.js +23 -0
  4. package/app/main.js +24 -3
  5. package/app/main.ts +7 -1
  6. package/app/pages/_layout.js +27 -0
  7. package/app/pages/async-work.js +65 -0
  8. package/app/pages/index.js +25 -5
  9. package/app/pages/index.ts +9 -0
  10. package/app/pages/router-example.js +24 -1
  11. package/app/pages/scroll-demo.ts +102 -0
  12. package/app/providers/ChildComponent.js +8 -2
  13. package/app/providers/ChildComponent.ts +47 -47
  14. package/app/providers/GrandchildComponent.js +19 -0
  15. package/app/providers/ParentComponent.js +5 -1
  16. package/app/routes/RouterExample.js +23 -1
  17. package/app/routes/TestResource.js +47 -0
  18. package/app/services.js +15 -0
  19. package/auto-imports.d.ts +12 -0
  20. package/framework/auto-import-preset.js +15 -9
  21. package/framework/core/async-context.js +27 -0
  22. package/framework/core/compiler/ast.js +167 -0
  23. package/framework/core/compiler/errors-list.js +47 -0
  24. package/framework/core/compiler/errors.js +107 -0
  25. package/framework/core/compiler/generator.js +363 -0
  26. package/framework/core/compiler/lexer.js +347 -0
  27. package/framework/core/compiler/main-compiler.js +115 -0
  28. package/framework/core/compiler/parser.js +414 -0
  29. package/framework/core/compiler/plugins/actions-plugin.js +263 -0
  30. package/framework/core/compiler/plugins/compiler-plugin.d.ts +5 -0
  31. package/framework/core/compiler/plugins/compiler-plugin.js +45 -0
  32. package/framework/core/compiler/plugins/file-router-plugin.js +301 -0
  33. package/framework/core/compiler/plugins/router-plugin.js +196 -0
  34. package/framework/core/compiler/transformer.js +398 -0
  35. package/framework/core/component.js +61 -23
  36. package/framework/core/di.js +187 -0
  37. package/framework/core/directives.js +40 -96
  38. package/framework/core/evaluator.js +1 -1
  39. package/framework/core/h.js +430 -0
  40. package/framework/core/hydration.js +83 -0
  41. package/framework/core/reconcile.js +151 -0
  42. package/framework/core/signal.js +269 -0
  43. package/framework/core/store.js +322 -81
  44. package/framework/index.js +5 -3
  45. package/framework/router/file-router.js +1 -1
  46. package/framework/router/router.js +113 -21
  47. package/framework/server/actions.js +173 -0
  48. package/framework/server/actions.server.js +88 -0
  49. package/framework/server/index.js +18 -0
  50. package/framework/types/actions.d.ts +50 -0
  51. package/framework/types/actions.server.d.ts +36 -0
  52. package/framework/types/compiler/ast.d.ts +166 -0
  53. package/framework/types/compiler/errors-codes.d.ts +23 -0
  54. package/framework/types/compiler/errors.d.ts +43 -0
  55. package/framework/types/compiler/generator.d.ts +8 -0
  56. package/framework/types/compiler/h.d.ts +46 -0
  57. package/framework/types/compiler/lexer.d.ts +27 -0
  58. package/framework/types/compiler/main-compiler.d.ts +60 -0
  59. package/framework/types/compiler/parser.d.ts +4 -0
  60. package/framework/types/compiler/plugins/actions.d.ts +30 -0
  61. package/framework/types/compiler/plugins/compiler-plugin.d.ts +5 -0
  62. package/framework/types/compiler/plugins/file-router-plugins.d.ts +32 -0
  63. package/framework/types/compiler/plugins/router-plugin.d.ts +24 -0
  64. package/framework/types/compiler/transformer.d.ts +28 -0
  65. package/framework/types/component.d.ts +89 -88
  66. package/framework/types/di.d.ts +43 -0
  67. package/framework/types/hydration.d.ts +30 -0
  68. package/framework/types/index.d.ts +38 -22
  69. package/framework/types/reconcile.d.ts +7 -0
  70. package/framework/types/router.d.ts +11 -1
  71. package/framework/types/server.d.ts +11 -0
  72. package/framework/types/signal.d.ts +142 -79
  73. package/framework/types/store.d.ts +66 -8
  74. package/ghid_go_fusee_integrat_go1_26.txt +276 -0
  75. package/ghid_rust_fusee_rust_1_95_0.txt +1118 -0
  76. package/package.json +44 -36
  77. package/vite.config.js +65 -47
@@ -0,0 +1,347 @@
1
+ import { CompileError, throwError } from "./errors.js";
2
+ import { ErrorCode } from "./errors-list.js";
3
+ import { createPos, createLoc } from "./ast.js";
4
+
5
+ export const TokenType = {
6
+ TAG_OPEN: "TAG_OPEN",
7
+ TAG_OPEN_CLOSE: "TAG_OPEN_CLOSE",
8
+ TAG_CLOSE: "TAG_CLOSE",
9
+ TAG_SELF_CLOSE: "TAG_SELF_CLOSE",
10
+ COMMENT: "COMMENT",
11
+ ATTR_NAME: "ATTR_NAME",
12
+ ATTR_EQUALS: "ATTR_EQUALS",
13
+ ATTR_VALUE: "ATTR_VALUE",
14
+ TEXT: "TEXT",
15
+ MUSTACHE_OPEN: "MUSTACHE_OPEN",
16
+ MUSTACHE_EXPR: "MUSTACHE_EXPR",
17
+ MUSTACHE_CLOSE: "MUSTACHE_CLOSE",
18
+ EOF: "EOF",
19
+ };
20
+
21
+ export function tokenize(source) {
22
+ const lexer = new Lexer(source);
23
+ return lexer.tokenize();
24
+ }
25
+
26
+ class Lexer {
27
+ constructor(source) {
28
+ this.source = source;
29
+ this.tokens = [];
30
+ this.pos = 0;
31
+ this.line = 1;
32
+ this.col = 1;
33
+ this._mode = "text";
34
+ }
35
+
36
+ tokenize() {
37
+ while (!this._eof()) {
38
+ if (this._mode === "text") {
39
+ this._readText();
40
+ } else if (this._mode === "tag") {
41
+ this._readInTag();
42
+ }
43
+ }
44
+ this._push(TokenType.EOF, "", this._startPos());
45
+ return this.tokens;
46
+ }
47
+
48
+ _readText() {
49
+ if (this._lookingAt("<!--")) {
50
+ this._readComment();
51
+ return;
52
+ }
53
+
54
+ if (this._lookingAt("</")) {
55
+ this._readClosingTag();
56
+ return;
57
+ }
58
+
59
+ if (this._peek() === "<" && this._isTagNameStart(this._peekAt(1))) {
60
+ this._readOpenTag();
61
+ return;
62
+ }
63
+
64
+ if (this._lookingAt("{{")) {
65
+ this._readMustache();
66
+ return;
67
+ }
68
+
69
+ const start = this._startPos();
70
+ let text = "";
71
+ while (!this._eof()) {
72
+ if (this._peek() === "<" || this._lookingAt("{{")) break;
73
+ text += this._advance();
74
+ }
75
+
76
+ if (text) this._push(TokenType.TEXT, text, start);
77
+ }
78
+
79
+ _readOpenTag() {
80
+ const start = this._startPos();
81
+ this._consume("<");
82
+ const name = this._readTagName();
83
+ this._pushAt(TokenType.TAG_OPEN, name, start);
84
+ this._mode = "tag";
85
+ }
86
+
87
+ _readClosingTag() {
88
+ const start = this._startPos();
89
+ this._consume("</");
90
+ const name = this._readTagName();
91
+ this._pushAt(TokenType.TAG_OPEN_CLOSE, name, start);
92
+ this._skipWhitespace();
93
+ if (!this._eof() && this._peek() === ">") {
94
+ const closeStart = this._startPos();
95
+ this._consume(">");
96
+ this._push(TokenType.TAG_CLOSE, ">", closeStart);
97
+ }
98
+ }
99
+
100
+ _readComment() {
101
+ const start = this._startPos();
102
+ this._consume("<!--");
103
+ let content = "";
104
+ while (!this._eof() && !this._lookingAt("-->")) {
105
+ content += this._advance();
106
+ }
107
+ if (this._eof()) {
108
+ throwError(
109
+ ErrorCode.MALFORMED_COMMENT,
110
+ createLoc(start, this._startPos()),
111
+ this.source,
112
+ );
113
+ }
114
+ this._consume("-->");
115
+ this._push(TokenType.COMMENT, content.trim(), start);
116
+ }
117
+
118
+ _readMustache() {
119
+ const openStart = this._startPos();
120
+ this._consume("{{");
121
+ this._push(TokenType.MUSTACHE_OPEN, "{{", openStart);
122
+
123
+ const exprStart = this._startPos();
124
+ let expr = "";
125
+ let depth = 0;
126
+ let inStr = false;
127
+ let strChar = null;
128
+
129
+ while (!this._eof()) {
130
+ const ch = this._peek();
131
+
132
+ if (inStr) {
133
+ if (ch === "\\") {
134
+ expr += this._advance();
135
+ expr += this._advance();
136
+ continue;
137
+ }
138
+ if (ch === strChar) {
139
+ inStr = false;
140
+ }
141
+ expr += this._advance();
142
+ continue;
143
+ }
144
+
145
+ if (ch === '"' || ch === "'" || ch === "`") {
146
+ inStr = true;
147
+ strChar = ch;
148
+ expr += this._advance();
149
+ continue;
150
+ }
151
+ if (ch === "{") {
152
+ depth++;
153
+ expr += this._advance();
154
+ continue;
155
+ }
156
+ if (ch === "}") {
157
+ if (depth > 0) {
158
+ depth--;
159
+ expr += this._advance();
160
+ continue;
161
+ }
162
+ if (this._peekAt(1) === "}") {
163
+ this._push(TokenType.MUSTACHE_EXPR, expr.trim(), exprStart);
164
+ const closeStart = this._startPos();
165
+ this._consume("}}");
166
+ this._push(TokenType.MUSTACHE_CLOSE, "}}", closeStart);
167
+ return;
168
+ }
169
+ }
170
+
171
+ expr += this._advance();
172
+ }
173
+
174
+ throwError(
175
+ ErrorCode.UNTERMINATED_MUSTACHE,
176
+ createLoc(openStart, this._startPos()),
177
+ this.source,
178
+ expr,
179
+ );
180
+ }
181
+
182
+ _readInTag() {
183
+ this._skipWhitespace();
184
+ if (this._eof()) return;
185
+
186
+ if (this._match("/>")) {
187
+ this._push(TokenType.TAG_SELF_CLOSE, "/>", this._startPos());
188
+ this._mode = "text";
189
+ return;
190
+ }
191
+
192
+ if (this._peek() === ">") {
193
+ this._consume(">");
194
+ this._push(TokenType.TAG_CLOSE, ">", this._startPos());
195
+ this._mode = "text";
196
+ return;
197
+ }
198
+
199
+ const start = this._startPos();
200
+ const name = this._readAttrName();
201
+ if (!name) return;
202
+
203
+ this._push(TokenType.ATTR_NAME, name, start);
204
+ this._skipWhitespace();
205
+
206
+ if (this._peek() === "=") {
207
+ this._consume("=");
208
+ this._push(TokenType.ATTR_EQUALS, "=", this._startPos());
209
+ this._skipWhitespace();
210
+ this._readAttrValue();
211
+ }
212
+ }
213
+
214
+ _readAttrName() {
215
+ let name = "";
216
+
217
+ if (this._peek() === "@") {
218
+ name += this._advance();
219
+ } else if (this._peek() === ":") {
220
+ name += this._advance();
221
+ }
222
+
223
+ while (!this._eof()) {
224
+ const ch = this._peek();
225
+ if (/[a-zA-Z0-9\-_.:]/.test(ch)) {
226
+ name += this._advance();
227
+ } else break;
228
+ }
229
+
230
+ return name || null;
231
+ }
232
+
233
+ _readAttrValue() {
234
+ if (this._eof()) return;
235
+ const quote = this._peek();
236
+ if (quote !== '"' && quote !== "'") {
237
+ const start = this._startPos();
238
+ let val = "";
239
+ while (!this._eof() && !/[\s>]/.test(this._peek())) {
240
+ val += this._advance();
241
+ }
242
+ this._push(TokenType.ATTR_VALUE, val, start);
243
+ return;
244
+ }
245
+
246
+ this._consume(quote);
247
+ const start = this._startPos();
248
+ let val = "";
249
+
250
+ while (!this._eof()) {
251
+ const ch = this._peek();
252
+ if (ch === quote) {
253
+ this._consume(quote);
254
+ break;
255
+ }
256
+ if (ch === "\\") {
257
+ this._advance();
258
+ val += this._advance();
259
+ continue;
260
+ }
261
+ val += this._advance();
262
+ }
263
+
264
+ this._push(TokenType.ATTR_VALUE, val, start);
265
+ }
266
+
267
+ _readTagName() {
268
+ let name = "";
269
+ while (!this._eof() && /[a-zA-Z0-9\-_.]/.test(this._peek())) {
270
+ name += this._advance();
271
+ }
272
+ return name;
273
+ }
274
+
275
+ _isTagNameStart(ch) {
276
+ return ch != null && /[a-zA-Z_]/.test(ch);
277
+ }
278
+
279
+ _eof() {
280
+ return this.pos >= this.source.length;
281
+ }
282
+
283
+ _peek() {
284
+ return this.source[this.pos];
285
+ }
286
+
287
+ _peekAt(n) {
288
+ return this.source[this.pos + n];
289
+ }
290
+
291
+ _lookingAt(str) {
292
+ return this.source.startsWith(str, this.pos);
293
+ }
294
+
295
+ _match(str) {
296
+ if (this._lookingAt(str)) {
297
+ for (const ch of str) this._advance();
298
+ return true;
299
+ }
300
+ return false;
301
+ }
302
+
303
+ _consume(expected) {
304
+ for (const ch of expected) {
305
+ if (this.source[this.pos] !== ch) {
306
+ throwError(
307
+ ErrorCode.UNEXPECTED_CHAR,
308
+ createLoc(this._startPos(), this._startPos()),
309
+ this.source,
310
+ this.source[this.pos],
311
+ );
312
+ }
313
+ this._advance();
314
+ }
315
+ }
316
+
317
+ _advance() {
318
+ const ch = this.source[this.pos++];
319
+ if (ch === "\n") {
320
+ this.line++;
321
+ this.col = 1;
322
+ } else {
323
+ this.col++;
324
+ }
325
+ return ch;
326
+ }
327
+
328
+ _skipWhitespace() {
329
+ while (!this._eof() && /\s/.test(this._peek())) this._advance();
330
+ }
331
+
332
+ _startPos() {
333
+ return createPos(this.line, this.col, this.pos);
334
+ }
335
+
336
+ _push(type, value, start) {
337
+ this.tokens.push({
338
+ type,
339
+ value,
340
+ loc: createLoc(start, this._startPos(), value),
341
+ });
342
+ }
343
+
344
+ _pushAt(type, value, start) {
345
+ this._push(type, value, start);
346
+ }
347
+ }
@@ -0,0 +1,115 @@
1
+ import { tokenize } from './lexer.js'
2
+ import { parse } from './parser.js'
3
+ import { transform } from './transformer.js'
4
+ import { generate } from './generator.js'
5
+ import { CompileError, ErrorCollector } from './errors.js'
6
+
7
+ export function compile(source, options = {}) {
8
+ const filename = options.filename ?? '<template>'
9
+ const components = new Set(options.components ?? [])
10
+ const collector = new ErrorCollector(source)
11
+
12
+ let tokens
13
+ try {
14
+ tokens = tokenize(source)
15
+ } catch (err) {
16
+ _rethrow(err, filename)
17
+ }
18
+
19
+ let ast
20
+ try {
21
+ ast = parse(tokens, source, components)
22
+ } catch (err) {
23
+ _rethrow(err, filename)
24
+ }
25
+
26
+ let warnings = []
27
+ try {
28
+ const result = transform(ast, { components, source, scope: options.scope })
29
+ ast = result.ast
30
+ warnings = result.warnings
31
+ } catch (err) {
32
+ _rethrow(err, filename)
33
+ }
34
+
35
+ if (options.throwOnWarning && warnings.length > 0) {
36
+ const w = warnings[0]
37
+ throw new CompileError(w.code, w.loc, source)
38
+ }
39
+
40
+ let code
41
+ try {
42
+ code = generate(ast, {
43
+ source,
44
+ runtimePath: options.runtimePath,
45
+ })
46
+ } catch (err) {
47
+ _rethrow(err, filename)
48
+ }
49
+
50
+ return { code, ast, tokens, warnings }
51
+ }
52
+
53
+ export function parseOnly(source, options = {}) {
54
+ const components = new Set(options.components ?? [])
55
+ const tokens = tokenize(source)
56
+ const ast = parse(tokens, source, components)
57
+ return { ast, tokens }
58
+ }
59
+
60
+ export function transformOnly(ast, options = {}) {
61
+ return transform(ast, {
62
+ components: new Set(options.components ?? []),
63
+ source: options.source ?? '',
64
+ scope: options.scope,
65
+ })
66
+ }
67
+
68
+ export function compileBatch(templates, sharedOptions = {}) {
69
+ return templates.map(({ id, source }) => {
70
+ try {
71
+ const { code, warnings } = compile(source, { ...sharedOptions, filename: id })
72
+ return { id, code, warnings, error: null }
73
+ } catch (err) {
74
+ return { id, code: null, warnings: [], error: err }
75
+ }
76
+ })
77
+ }
78
+
79
+ export function fuseePlugin(pluginOptions = {}) {
80
+ return {
81
+ name: 'vite-plugin-fusee',
82
+
83
+ transform(src, id) {
84
+ if (!id.endsWith('.fusee') && !id.endsWith('.fhtml')) return null
85
+
86
+ const { code, warnings } = compile(src, {
87
+ filename: id,
88
+ runtimePath: pluginOptions.runtimePath,
89
+ components: pluginOptions.components,
90
+ scope: pluginOptions.scope,
91
+ })
92
+
93
+ for (const w of warnings) {
94
+ this.warn(w.format(id))
95
+ }
96
+
97
+ return { code, map: null }
98
+ }
99
+ }
100
+ }
101
+
102
+ export { fileRouterPlugin } from './plugins/file-router-plugin.js'
103
+ export { actionsPlugin } from './plugins/actions-plugin.js'
104
+ export { routerPlugin } from './plugins/router-plugin.js'
105
+ export { compileFileRoutes, generateRoutesModule, generateRouteTypes, validateRoutes as validateFileRoutes,} from './plugins/file-router-plugin.js'
106
+ export { validateActions, generateClientStubs, generateServerRoutes, generateActionTypes,} from './plugins/actions-plugin.js'
107
+ export { validateRoutes, generateRouterTypes,} from './plugins/router-plugin.js'
108
+
109
+ function _rethrow(err, filename) {
110
+ if (err instanceof CompileError) {
111
+ err.message = err.format(filename)
112
+ throw err
113
+ }
114
+ throw err
115
+ }