fusee-framework 1.8.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 (49) hide show
  1. package/README.md +64 -3
  2. package/app/benchmark/vite.config.js +23 -0
  3. package/auto-imports.d.ts +4 -0
  4. package/framework/auto-import-preset.js +3 -1
  5. package/framework/core/async-context.js +27 -0
  6. package/framework/core/compiler/ast.js +167 -0
  7. package/framework/core/compiler/errors-list.js +47 -0
  8. package/framework/core/compiler/errors.js +107 -0
  9. package/framework/core/compiler/generator.js +363 -0
  10. package/framework/core/compiler/lexer.js +347 -0
  11. package/framework/core/compiler/main-compiler.js +115 -0
  12. package/framework/core/compiler/parser.js +414 -0
  13. package/framework/core/compiler/plugins/actions-plugin.js +263 -0
  14. package/framework/core/compiler/plugins/compiler-plugin.d.ts +5 -0
  15. package/framework/core/compiler/plugins/compiler-plugin.js +45 -0
  16. package/framework/core/compiler/plugins/file-router-plugin.js +301 -0
  17. package/framework/core/compiler/plugins/router-plugin.js +196 -0
  18. package/framework/core/compiler/transformer.js +398 -0
  19. package/framework/core/component.js +34 -10
  20. package/framework/core/evaluator.js +1 -1
  21. package/framework/core/h.js +430 -0
  22. package/framework/core/hydration.js +83 -0
  23. package/framework/core/signal.js +17 -15
  24. package/framework/server/actions.js +173 -0
  25. package/framework/server/actions.server.js +88 -0
  26. package/framework/server/index.js +18 -0
  27. package/framework/types/actions.d.ts +50 -0
  28. package/framework/types/actions.server.d.ts +36 -0
  29. package/framework/types/compiler/ast.d.ts +166 -0
  30. package/framework/types/compiler/errors-codes.d.ts +23 -0
  31. package/framework/types/compiler/errors.d.ts +43 -0
  32. package/framework/types/compiler/generator.d.ts +8 -0
  33. package/framework/types/compiler/h.d.ts +46 -0
  34. package/framework/types/compiler/lexer.d.ts +27 -0
  35. package/framework/types/compiler/main-compiler.d.ts +60 -0
  36. package/framework/types/compiler/parser.d.ts +4 -0
  37. package/framework/types/compiler/plugins/actions.d.ts +30 -0
  38. package/framework/types/compiler/plugins/compiler-plugin.d.ts +5 -0
  39. package/framework/types/compiler/plugins/file-router-plugins.d.ts +32 -0
  40. package/framework/types/compiler/plugins/router-plugin.d.ts +24 -0
  41. package/framework/types/compiler/transformer.d.ts +28 -0
  42. package/framework/types/hydration.d.ts +30 -0
  43. package/framework/types/index.d.ts +6 -0
  44. package/framework/types/server.d.ts +11 -0
  45. package/framework/types/signal.d.ts +2 -7
  46. package/ghid_go_fusee_integrat_go1_26.txt +276 -0
  47. package/ghid_rust_fusee_rust_1_95_0.txt +1118 -0
  48. package/package.json +44 -36
  49. package/vite.config.js +65 -53
@@ -0,0 +1,173 @@
1
+ import { signal, batch } from '../core/signal.js'
2
+ import { getCurrentInstance } from '../core/component.js'
3
+
4
+ const ACTION_BASE_URL = '/__fusee/actions'
5
+ const _actionHydrationRegistry = new Map()
6
+
7
+ export function defineAction(fnOrName, opts = {}) {
8
+ const name = opts.name
9
+ || (typeof fnOrName === 'function' ? fnOrName.name : fnOrName)
10
+
11
+ if (!name) {
12
+ throw new Error('[fusee] defineAction() client stub: nu s-a putut determina numele acțiunii')
13
+ }
14
+
15
+ return createActionProxy(name, opts)
16
+ }
17
+
18
+ export function createActionProxy(name, opts = {}) {
19
+ const baseUrl = opts.baseUrl ?? ACTION_BASE_URL
20
+
21
+ async function actionProxy(...args) {
22
+ const res = await fetch(`${baseUrl}/${name}`, {
23
+ method: 'POST',
24
+ headers: {
25
+ 'Content-Type': 'application/json',
26
+ ...(opts.headers ?? {})
27
+ },
28
+ body: JSON.stringify({ args })
29
+ })
30
+
31
+ const json = await res.json()
32
+
33
+ if (!res.ok) {
34
+ const err = new Error(json.error ?? `Action "${name}" failed (${res.status})`)
35
+ err.status = res.status
36
+ err.code = json.code
37
+ throw err
38
+ }
39
+
40
+ return json.data
41
+ }
42
+
43
+ actionProxy._isAction = true
44
+ actionProxy._actionName = name
45
+
46
+ return actionProxy
47
+ }
48
+
49
+ export function useAction(action, opts = {}) {
50
+ if (typeof action !== 'function') {
51
+ throw new Error('[fusee] useAction() requires an action function (result of defineAction or createActionProxy)')
52
+ }
53
+
54
+ const pending = signal(false)
55
+ const data = signal(undefined)
56
+ const error = signal(undefined)
57
+
58
+ const { onSuccess, onError, resetOnCall = true } = opts
59
+
60
+ let callId = 0
61
+
62
+ async function execute(...args) {
63
+ const id = ++callId
64
+
65
+ batch(() => {
66
+ pending(true)
67
+ if (resetOnCall) {
68
+ data(undefined)
69
+ error(undefined)
70
+ }
71
+ })
72
+
73
+ try {
74
+ const result = await action(...args)
75
+
76
+ if (id !== callId) return result
77
+
78
+ batch(() => {
79
+ data(result)
80
+ pending(false)
81
+ })
82
+
83
+ if (typeof onSuccess === 'function') {
84
+ onSuccess(result)
85
+ }
86
+
87
+ return result
88
+ } catch (err) {
89
+ if (id !== callId) return
90
+
91
+ batch(() => {
92
+ error(err)
93
+ pending(false)
94
+ })
95
+
96
+ if (typeof onError === 'function') {
97
+ onError(err)
98
+ } else {
99
+ console.error(`[fusee] useAction("${action._actionName ?? '?'}") error:`, err)
100
+ }
101
+ }
102
+ }
103
+
104
+ function reset() {
105
+ batch(() => {
106
+ pending(false)
107
+ data(undefined)
108
+ error(undefined)
109
+ })
110
+ callId++
111
+ }
112
+
113
+ const instance = getCurrentInstance()
114
+ if (instance) {
115
+ instance._unmountHooks.push(() => {
116
+ callId++
117
+ })
118
+ }
119
+
120
+ return { execute, pending, data, error, reset }
121
+ }
122
+
123
+ export function hydrateAction(actionName, data, opts = {}) {
124
+ const key = `action:${actionName}`
125
+ _actionHydrationRegistry.set(key, {
126
+ data,
127
+ timestamp: Date.now(),
128
+ staleTime: opts.staleTime ?? 0
129
+ })
130
+ }
131
+
132
+ export function getHydratedAction(actionName, staleTime) {
133
+ const key = `action:${actionName}`
134
+ const entry = _actionHydrationRegistry.get(key)
135
+ if (!entry) return undefined
136
+
137
+ if (staleTime !== undefined && (Date.now() - entry.timestamp) > staleTime) {
138
+ return undefined
139
+ }
140
+ if (entry.staleTime && (Date.now() - entry.timestamp) > entry.staleTime) {
141
+ return undefined
142
+ }
143
+
144
+ return entry.data
145
+ }
146
+
147
+ export function clearActionHydration() {
148
+ _actionHydrationRegistry.clear()
149
+ }
150
+
151
+ export function extractActionHydration() {
152
+ const snapshot = {}
153
+ for (const [key, entry] of _actionHydrationRegistry) {
154
+ snapshot[key] = {
155
+ data: entry.data,
156
+ timestamp: entry.timestamp,
157
+ staleTime: entry.staleTime
158
+ }
159
+ }
160
+ return snapshot
161
+ }
162
+
163
+ export function loadActionHydration(snapshot) {
164
+ if (!snapshot || typeof snapshot !== 'object') return
165
+
166
+ for (const [key, entry] of Object.entries(snapshot)) {
167
+ _actionHydrationRegistry.set(key, {
168
+ data: entry.data,
169
+ timestamp: entry.timestamp,
170
+ staleTime: entry.staleTime
171
+ })
172
+ }
173
+ }
@@ -0,0 +1,88 @@
1
+ import { withRequestContext, createRequestContext } from './index.js'
2
+
3
+ const _actionRegistry = new Map()
4
+
5
+ export function defineAction(fn, opts = {}) {
6
+ if (typeof fn !== 'function') {
7
+ throw new Error('[fusee] defineAction() requires a function')
8
+ }
9
+
10
+ const name = opts.name || fn.name
11
+ if (!name) {
12
+ throw new Error(
13
+ '[fusee] defineAction(): funcția trebuie să aibă un nume sau să specifici opts.name'
14
+ )
15
+ }
16
+
17
+ const wrapped = async function (...args) {
18
+ if (opts.authorize) {
19
+ await opts.authorize(...args)
20
+ }
21
+ return fn(...args)
22
+ }
23
+
24
+ wrapped._isAction = true
25
+ wrapped._actionName = name
26
+ _actionRegistry.set(name, { fn: wrapped, opts })
27
+
28
+ return wrapped
29
+ }
30
+
31
+ export async function handleActionRequest(req, res) {
32
+ let actionName
33
+ if (req.params?.name) {
34
+ actionName = req.params.name
35
+ } else {
36
+ const url = new URL(req.url, 'http://localhost')
37
+ const parts = url.pathname.split('/')
38
+ actionName = parts[parts.length - 1]
39
+ }
40
+
41
+ const entry = _actionRegistry.get(actionName)
42
+ if (!entry) {
43
+ return _sendJson(res, 404, { error: `Action "${actionName}" not found` })
44
+ }
45
+
46
+ let body
47
+ try {
48
+ body = req.body ?? (await _parseBody(req))
49
+ } catch {
50
+ return _sendJson(res, 400, { error: 'Invalid JSON body' })
51
+ }
52
+
53
+ const args = Array.isArray(body?.args) ? body.args : body != null ? [body] : []
54
+ const ctx = createRequestContext()
55
+
56
+ try {
57
+ const data = await withRequestContext(ctx, () => entry.fn(...args))
58
+ return _sendJson(res, 200, { data: data ?? null })
59
+ } catch (err) {
60
+ const isPublic = err?.expose === true
61
+ console.error(`[fusee] Action "${actionName}" threw:`, err)
62
+ return _sendJson(res, err?.status ?? 500, {
63
+ error: isPublic ? err.message : 'Internal server error',
64
+ code: err?.code
65
+ })
66
+ }
67
+ }
68
+
69
+ export function getRegisteredActions() {
70
+ return [..._actionRegistry.keys()]
71
+ }
72
+
73
+ async function _parseBody(req) {
74
+ const chunks = []
75
+ for await (const chunk of req) chunks.push(chunk)
76
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'))
77
+ }
78
+
79
+ function _sendJson(res, status, body) {
80
+ if (typeof res.status === 'function') {
81
+ return res.status(status).json(body)
82
+ }
83
+
84
+ return new Response(JSON.stringify(body), {
85
+ status,
86
+ headers: { 'Content-Type': 'application/json' }
87
+ })
88
+ }
@@ -0,0 +1,18 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
2
+ import { _registerALS } from '../core/async-context.js'
3
+
4
+ const _als = new AsyncLocalStorage()
5
+ _registerALS(_als)
6
+
7
+ export function createRequestContext() {
8
+ return {
9
+ inFlightMaps: {
10
+ byKey: new Map(),
11
+ byFetcher: new WeakMap()
12
+ }
13
+ }
14
+ }
15
+
16
+ export function withRequestContext(ctx, fn) {
17
+ return _als.run(ctx, fn)
18
+ }
@@ -0,0 +1,50 @@
1
+ export interface ActionOptions {
2
+ name?: string
3
+ baseUrl?: string
4
+ headers?: Record<string, string>
5
+ }
6
+
7
+ export interface UseActionOptions {
8
+ onSuccess?: (data: any) => void
9
+ onError?: (error: Error) => void
10
+ resetOnCall?: boolean
11
+ }
12
+
13
+ export interface ActionReturn {
14
+ execute: (...args: any[]) => Promise<any>
15
+ pending: Signal<boolean>
16
+ data: Signal<any>
17
+ error: Signal<any>
18
+ reset: () => void
19
+ }
20
+
21
+ export interface ActionProxy extends Function {
22
+ _isAction: boolean
23
+ _actionName: string
24
+ }
25
+
26
+ export declare function defineAction(fnOrName: Function | string, opts?: ActionOptions): ActionProxy
27
+ export declare function createActionProxy(name: string, opts?: ActionOptions): ActionProxy
28
+ export declare function useAction(action: ActionProxy, opts?: UseActionOptions): ActionReturn
29
+
30
+ // ─── Hydration Support ─────────────────────────────────────────────────────
31
+
32
+ export interface ActionHydrationOptions {
33
+ staleTime?: number
34
+ }
35
+
36
+ export interface ActionHydrationEntry {
37
+ data: any
38
+ timestamp: number
39
+ staleTime: number
40
+ }
41
+
42
+ export interface ActionHydrationSnapshot {
43
+ [key: string]: ActionHydrationEntry
44
+ }
45
+
46
+ export declare function hydrateAction(actionName: string, data: any, opts?: ActionHydrationOptions): void
47
+ export declare function getHydratedAction(actionName: string, staleTime?: number): any
48
+ export declare function clearActionHydration(): void
49
+ export declare function extractActionHydration(): ActionHydrationSnapshot
50
+ export declare function loadActionHydration(snapshot: ActionHydrationSnapshot): void
@@ -0,0 +1,36 @@
1
+ export interface ActionServerOptions {
2
+ name?: string
3
+ authorize?: (...args: any[]) => Promise<void> | void
4
+ }
5
+
6
+ export interface RegisteredAction {
7
+ fn: Function
8
+ opts: ActionServerOptions
9
+ }
10
+
11
+ export interface ActionRegistry {
12
+ get(name: string): RegisteredAction | undefined
13
+ set(name: string, entry: RegisteredAction): void
14
+ keys(): IterableIterator<string>
15
+ }
16
+
17
+ export interface RequestLike {
18
+ params?: { name?: string }
19
+ body?: any
20
+ url?: string
21
+ }
22
+
23
+ export interface ResponseLike {
24
+ status(code: number): ResponseLike
25
+ json(body: any): any
26
+ }
27
+
28
+ export interface ActionError extends Error {
29
+ status?: number
30
+ code?: string
31
+ expose?: boolean
32
+ }
33
+
34
+ export declare function defineAction(fn: Function, opts?: ActionServerOptions): Function
35
+ export declare function handleActionRequest(req: RequestLike, res: ResponseLike): Promise<void>
36
+ export declare function getRegisteredActions(): string[]
@@ -0,0 +1,166 @@
1
+ export declare const NodeType: {
2
+ readonly ROOT: 'Root'
3
+ readonly ELEMENT: 'Element'
4
+ readonly COMPONENT: 'Component'
5
+ readonly TEXT: 'Text'
6
+ readonly INTERPOLATION: 'Interpolation'
7
+ readonly EXPRESSION: 'Expression'
8
+ readonly ATTRIBUTE: 'Attribute'
9
+ readonly BINDING: 'Binding'
10
+ readonly EVENT: 'Event'
11
+ readonly DIRECTIVE: 'Directive'
12
+ readonly SLOT_OUTLET: 'SlotOutlet'
13
+ readonly SLOT_CONTENT: 'SlotContent'
14
+ }
15
+
16
+ export type NodeTypeValue = typeof NodeType[keyof typeof NodeType]
17
+
18
+ export interface Position {
19
+ line: number
20
+ col: number
21
+ offset: number
22
+ }
23
+
24
+ export interface SourceLocation {
25
+ start: Position
26
+ end: Position
27
+ source?: string
28
+ }
29
+
30
+ export interface BaseNode {
31
+ type: NodeTypeValue | 'If'
32
+ loc: SourceLocation | null
33
+ }
34
+
35
+ export interface RootNode extends BaseNode {
36
+ type: 'Root'
37
+ children: ChildNode[]
38
+ _hoisted?: AnyNode[]
39
+ }
40
+
41
+ export interface ElementNode extends BaseNode {
42
+ type: 'Element'
43
+ tag: string
44
+ props: PropNode[]
45
+ children: ChildNode[]
46
+ selfClosing: boolean
47
+ isStatic: boolean
48
+ hoisted: boolean
49
+ }
50
+
51
+ export interface ComponentNode extends BaseNode {
52
+ type: 'Component'
53
+ name: string
54
+ props: PropNode[]
55
+ slots: Record<string, ChildNode[]>
56
+ isStatic: boolean
57
+ }
58
+
59
+ export interface TextNode extends BaseNode {
60
+ type: 'Text'
61
+ content: string
62
+ isStatic: true
63
+ }
64
+
65
+ export interface InterpolationNode extends BaseNode {
66
+ type: 'Interpolation'
67
+ expression: ExpressionNode
68
+ isStatic: boolean
69
+ }
70
+
71
+ export interface ExpressionNode extends BaseNode {
72
+ type: 'Expression'
73
+ content: string
74
+ isStatic: boolean
75
+ _isForKey?: boolean
76
+ }
77
+
78
+ export interface AttributeNode extends BaseNode {
79
+ type: 'Attribute'
80
+ name: string
81
+ value: string | null
82
+ }
83
+
84
+ export interface BindingNode extends BaseNode {
85
+ type: 'Binding'
86
+ name: string
87
+ expression: ExpressionNode
88
+ isProp: boolean
89
+ }
90
+
91
+ export interface EventNode extends BaseNode {
92
+ type: 'Event'
93
+ name: string
94
+ expression: ExpressionNode
95
+ modifiers: string[]
96
+ }
97
+
98
+ export type DirectiveName = 'if' | 'else-if' | 'else' | 'for' | 'model' | 'show' | 'once' | 'ref' | 'html' | string
99
+
100
+ export interface DirectiveNode extends BaseNode {
101
+ type: 'Directive'
102
+ name: DirectiveName
103
+ expression: ExpressionNode | null
104
+ arg: ForArg | null
105
+ }
106
+
107
+ export interface SlotOutletNode extends BaseNode {
108
+ type: 'SlotOutlet'
109
+ slotName: string
110
+ fallback: ChildNode[]
111
+ }
112
+
113
+ export interface SlotContentNode extends BaseNode {
114
+ type: 'SlotContent'
115
+ slotName: string
116
+ children: ChildNode[]
117
+ }
118
+
119
+ export interface IfNode {
120
+ type: 'If'
121
+ branches: IfBranch[]
122
+ loc: SourceLocation | null
123
+ isStatic: false
124
+ }
125
+
126
+ export interface IfBranch {
127
+ condition: ExpressionNode | null
128
+ node: ElementNode | ComponentNode
129
+ }
130
+
131
+ export interface ForArg {
132
+ item: string
133
+ source: string
134
+ index: string | null
135
+ loc: SourceLocation | null
136
+ }
137
+
138
+ export type PropNode = AttributeNode | BindingNode | EventNode | DirectiveNode
139
+ export type ChildNode = ElementNode | ComponentNode | TextNode | InterpolationNode | SlotOutletNode | SlotContentNode | IfNode
140
+ export type AnyNode = RootNode | ChildNode | PropNode | ExpressionNode | ForArg
141
+
142
+ export declare function createLoc(start: Position, end: Position, source?: string): SourceLocation
143
+ export declare function createPos(line: number, col: number, offset: number): Position
144
+ export declare function createRoot(children?: ChildNode[], loc?: SourceLocation | null): RootNode
145
+ export declare function createElement(tag: string, props?: PropNode[], children?: ChildNode[], selfClosing?: boolean, loc?: SourceLocation | null): ElementNode
146
+ export declare function createComponent(name: string, props?: PropNode[], slots?: Record<string, ChildNode[]>, loc?: SourceLocation | null): ComponentNode
147
+ export declare function createText(content: string, loc?: SourceLocation | null): TextNode
148
+ export declare function createInterpolation(expression: ExpressionNode, loc?: SourceLocation | null): InterpolationNode
149
+ export declare function createExpression(content: string, isStatic?: boolean, loc?: SourceLocation | null): ExpressionNode
150
+ export declare function createAttribute(name: string, value: string | null, loc?: SourceLocation | null): AttributeNode
151
+ export declare function createBinding(name: string, expression: ExpressionNode, isProp?: boolean, loc?: SourceLocation | null): BindingNode
152
+ export declare function createEvent(name: string, expression: ExpressionNode, modifiers?: string[], loc?: SourceLocation | null): EventNode
153
+ export declare function createDirective(name: DirectiveName, expression?: ExpressionNode | null, arg?: ForArg | null, loc?: SourceLocation | null): DirectiveNode
154
+ export declare function createSlotOutlet(slotName?: string, fallback?: ChildNode[], loc?: SourceLocation | null): SlotOutletNode
155
+ export declare function createSlotContent(slotName?: string, children?: ChildNode[], loc?: SourceLocation | null): SlotContentNode
156
+ export declare function createForArg(item: string, source: string, index?: string | null, loc?: SourceLocation | null): ForArg
157
+
158
+ export declare function isElement(node: AnyNode | null | undefined): node is ElementNode
159
+ export declare function isComponent(node: AnyNode | null | undefined): node is ComponentNode
160
+ export declare function isText(node: AnyNode | null | undefined): node is TextNode
161
+ export declare function isInterpolation(node: AnyNode | null | undefined): node is InterpolationNode
162
+ export declare function isDirective(node: AnyNode | null | undefined, name?: DirectiveName): node is DirectiveNode
163
+ export declare function isStaticText(node: AnyNode | null | undefined): boolean
164
+ export declare function findDirective(element: ElementNode | ComponentNode, name: DirectiveName): DirectiveNode | null
165
+ export declare function getEvents(element: ElementNode | ComponentNode): EventNode[]
166
+ export declare function cloneNode<T extends AnyNode>(node: T): T
@@ -0,0 +1,23 @@
1
+ export declare const ErrorCode: {
2
+ readonly UNEXPECTED_CHAR: 'E001'
3
+ readonly UNTERMINATED_STRING: 'E002'
4
+ readonly UNTERMINATED_MUSTACHE: 'E003'
5
+ readonly UNTERMINATED_TAG: 'E004'
6
+ readonly MALFORMED_COMMENT: 'E005'
7
+ readonly UNEXPECTED_TOKEN: 'P001'
8
+ readonly MISSING_CLOSING_TAG: 'P002'
9
+ readonly UNEXPECTED_CLOSING_TAG: 'P003'
10
+ readonly INVALID_DIRECTIVE_SYNTAX: 'P004'
11
+ readonly INVALID_FOR_SYNTAX: 'P005'
12
+ readonly DUPLICATE_KEY: 'P006'
13
+ readonly V_ELSE_NO_IF: 'P007'
14
+ readonly EMPTY_EXPRESSION: 'P008'
15
+ readonly INVALID_SLOT_NAME: 'P009'
16
+ readonly DUPLICATE_DIRECTIVE: 'T001'
17
+ readonly FOR_MISSING_KEY: 'T002'
18
+ readonly MODEL_ON_NON_INPUT: 'T003'
19
+ readonly COMPONENT_NOT_REGISTERED: 'T004'
20
+ readonly UNKNOWN_IDENTIFIER: 'S001'
21
+ readonly STATIC_FOR_KEY: 'S002'
22
+ readonly UNKNOWN_NODE_TYPE: 'G001'
23
+ }
@@ -0,0 +1,43 @@
1
+ import type { SourceLocation } from './ast.js'
2
+ import type { ErrorCode } from './errors-list.js'
3
+
4
+ export type ErrorCodeValue = typeof ErrorCode[keyof typeof ErrorCode]
5
+
6
+ export declare class CompileError extends Error {
7
+ readonly name: 'CompileError'
8
+ readonly code: ErrorCodeValue
9
+ readonly loc: SourceLocation | null
10
+ readonly source: string
11
+
12
+ constructor(code: ErrorCodeValue, loc: SourceLocation | null, source: string, ...args: string[])
13
+
14
+ format(filePath?: string): string
15
+ _buildSnippet(): string
16
+ }
17
+
18
+ export declare class CompileWarning {
19
+ readonly message: string
20
+ readonly code: ErrorCodeValue
21
+ readonly loc: SourceLocation | null
22
+ readonly source: string
23
+
24
+ constructor(code: ErrorCodeValue, loc: SourceLocation | null, source: string, ...args: string[])
25
+
26
+ format(filePath?: string): string
27
+ }
28
+
29
+ export declare class ErrorCollector {
30
+ readonly source: string
31
+ readonly errors: CompileError[]
32
+ readonly warnings: CompileWarning[]
33
+ readonly hasErrors: boolean
34
+ readonly hasWarnings: boolean
35
+
36
+ constructor(source: string)
37
+
38
+ error(code: ErrorCodeValue, loc: SourceLocation | null, ...args: string[]): CompileError
39
+ warn(code: ErrorCodeValue, loc: SourceLocation | null, ...args: string[]): CompileWarning
40
+ throwIfAny(): void
41
+ }
42
+
43
+ export declare function throwError(code: ErrorCodeValue, loc: SourceLocation | null, source: string, ...args: string[]): never
@@ -0,0 +1,8 @@
1
+ import type { RootNode } from './ast.js'
2
+
3
+ export interface GenerateOptions {
4
+ runtimePath?: string
5
+ source?: string
6
+ }
7
+
8
+ export declare function generate(ast: RootNode, options?: GenerateOptions): string
@@ -0,0 +1,46 @@
1
+ export interface FNode {
2
+ node: Node
3
+ effects: Array<() => void>
4
+ _isIf?: boolean
5
+ _isFor?: boolean
6
+ _isSlot?: boolean
7
+ _tag?: string
8
+ _component?: ComponentApi
9
+ _ifBranchNodes?: () => FNode[]
10
+ _getNodes?: () => FNode[]
11
+ _slotNodes?: FNode[]
12
+ props?: Record<string, unknown>
13
+ children?: FNode[]
14
+ }
15
+
16
+ export interface ComponentApi {
17
+ render(container: HTMLElement): unknown
18
+ unmount(): void
19
+ instance: unknown
20
+ }
21
+
22
+ export type StaticPropValue = string | boolean | null
23
+ export type PropGetter<T = unknown> = () => T
24
+ export interface EventDescriptor {
25
+ handler: ((...args: unknown[]) => void) | null
26
+ modifiers: string[]
27
+ }
28
+
29
+ export type SlotMap = Record<string, () => FNode[]>
30
+ export type PropsMap = Record<string, StaticPropValue | PropGetter | EventDescriptor | true>
31
+
32
+ export declare function h(tag: string, props?: PropsMap, children?: FNode[], isStatic?: boolean): FNode
33
+ export declare function hText(value: string | (() => string)): FNode
34
+ export declare function hIf(branches: Array<[(() => boolean) | null, () => FNode[]]>): FNode
35
+ export declare function hFor<T>(sourceGetter: () => T[], renderItem: (item: T, index?: number) => FNode, keyFn: (item: T, index?: number) => unknown): FNode
36
+ export declare function hSlot(slots: SlotMap | null | undefined, name: string, fallback?: FNode[]): FNode
37
+ export declare function createComponent(name: string, ComponentFn: ((...args: unknown[]) => ComponentApi) | undefined | null, rawProps?: PropsMap, rawSlots?: SlotMap): FNode
38
+
39
+ export interface MountedApp {
40
+ unmount(): void
41
+ }
42
+
43
+ export declare function mount(renderFn: (ctx: unknown, components: Record<string, unknown>) => FNode[], ctx: unknown, components: Record<string, unknown>, container: HTMLElement): MountedApp
44
+
45
+ export declare const _effect: (fn: () => void) => () => void
46
+ export declare const _batch: <T>(fn: () => T) => T
@@ -0,0 +1,27 @@
1
+ import type { SourceLocation } from './ast.js'
2
+
3
+ export declare const TokenType: {
4
+ readonly TAG_OPEN: 'TAG_OPEN'
5
+ readonly TAG_OPEN_CLOSE: 'TAG_OPEN_CLOSE'
6
+ readonly TAG_CLOSE: 'TAG_CLOSE'
7
+ readonly TAG_SELF_CLOSE: 'TAG_SELF_CLOSE'
8
+ readonly COMMENT: 'COMMENT'
9
+ readonly ATTR_NAME: 'ATTR_NAME'
10
+ readonly ATTR_EQUALS: 'ATTR_EQUALS'
11
+ readonly ATTR_VALUE: 'ATTR_VALUE'
12
+ readonly TEXT: 'TEXT'
13
+ readonly MUSTACHE_OPEN: 'MUSTACHE_OPEN'
14
+ readonly MUSTACHE_EXPR: 'MUSTACHE_EXPR'
15
+ readonly MUSTACHE_CLOSE: 'MUSTACHE_CLOSE'
16
+ readonly EOF: 'EOF'
17
+ }
18
+
19
+ export type TokenTypeValue = typeof TokenType[keyof typeof TokenType]
20
+
21
+ export interface Token {
22
+ type: TokenTypeValue
23
+ value: string
24
+ loc: SourceLocation
25
+ }
26
+
27
+ export declare function tokenize(source: string): Token[]