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
|
@@ -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,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[]
|