fusee-framework 1.5.3 → 1.7.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.
- package/README.md +30 -13
- package/app/benchmark/benchmark.js +633 -0
- package/app/benchmark/index.html +102 -0
- package/app/benchmark/styles.css +249 -0
- package/app/components/Counter.js +17 -7
- package/app/components/Counter.ts +1 -1
- package/app/components/CounterSection.js +3 -4
- package/app/main.js +29 -62
- package/app/main.ts +72 -63
- package/app/pages/404.js +16 -0
- package/app/pages/[...all].js +35 -0
- package/app/pages/[...all].ts +35 -0
- package/app/pages/_layout.js +26 -0
- package/app/pages/_layout.ts +26 -0
- package/app/pages/about.js +23 -0
- package/app/pages/about.ts +29 -0
- package/app/pages/composables.js +158 -0
- package/app/pages/composables.ts +158 -0
- package/app/pages/dynamic.js +40 -0
- package/app/pages/dynamic.ts +40 -0
- package/app/pages/index.js +117 -0
- package/app/pages/index.ts +78 -0
- package/app/pages/login.ts +21 -0
- package/app/pages/objects/[id].js +56 -0
- package/app/pages/objects/[id].ts +56 -0
- package/app/pages/posts/[category]/[slug].js +56 -0
- package/app/pages/posts/[category]/[slug].ts +56 -0
- package/app/pages/router-example.js +56 -0
- package/app/pages/router-example.ts +56 -0
- package/app/pages/test-for.js +65 -0
- package/app/pages/test-for.ts +80 -0
- package/app/pages/users/[id].js +24 -0
- package/app/pages/users/[id].ts +46 -0
- package/app/pages/users/index.js +22 -0
- package/app/pages/users/index.ts +29 -0
- package/app/pages/users.js +43 -0
- package/app/pages/users.ts +78 -0
- package/app/routes/About.js +1 -1
- package/app/routes/About.ts +1 -1
- package/app/routes/AuthRoutes.ts +41 -0
- package/app/routes/Home.js +9 -0
- package/app/routes/NotFound.js +16 -0
- package/app/routes/NotFound.ts +16 -0
- package/app/routes/RouterExample.js +56 -0
- package/app/routes/RouterExample.ts +56 -0
- package/app/routes/WildcardDemo.js +35 -0
- package/app/routes/WildcardDemo.ts +35 -0
- package/auto-imports.d.ts +1 -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/bin/index.js +38 -0
- package/create-fusee-go/cmd/generate.go +72 -0
- package/create-fusee-go/cmd/init.go +38 -0
- package/create-fusee-go/cmd/root.go +121 -0
- package/create-fusee-go/go.mod +10 -0
- package/create-fusee-go/go.sum +10 -0
- package/create-fusee-go/internal/assets/assets.go +78 -0
- package/create-fusee-go/internal/assets/embed/framework/auto-import-preset.js +9 -0
- package/create-fusee-go/internal/assets/embed/framework/core/compiler.js +253 -0
- package/create-fusee-go/internal/assets/embed/framework/core/component.js +266 -0
- package/create-fusee-go/internal/assets/embed/framework/core/composable.js +27 -0
- package/create-fusee-go/internal/assets/embed/framework/core/directives.js +875 -0
- package/create-fusee-go/internal/assets/embed/framework/core/evaluator.js +153 -0
- package/create-fusee-go/internal/assets/embed/framework/core/event-delegation.js +191 -0
- package/create-fusee-go/internal/assets/embed/framework/core/signal.js +412 -0
- package/create-fusee-go/internal/assets/embed/framework/core/store.js +81 -0
- package/create-fusee-go/internal/assets/embed/framework/index.d.ts +3 -0
- package/create-fusee-go/internal/assets/embed/framework/index.js +10 -0
- package/create-fusee-go/internal/assets/embed/framework/router/file-router.js +177 -0
- package/create-fusee-go/internal/assets/embed/framework/router/router.js +462 -0
- package/create-fusee-go/internal/assets/embed/framework/types/compiler.d.ts +15 -0
- package/create-fusee-go/internal/assets/embed/framework/types/component.d.ts +88 -0
- package/create-fusee-go/internal/assets/embed/framework/types/composable.d.ts +14 -0
- package/create-fusee-go/internal/assets/embed/framework/types/directives.d.ts +55 -0
- package/create-fusee-go/internal/assets/embed/framework/types/evaluator.d.ts +13 -0
- package/create-fusee-go/internal/assets/embed/framework/types/event-delegation.d.ts +32 -0
- package/create-fusee-go/internal/assets/embed/framework/types/index.d.ts +22 -0
- package/create-fusee-go/internal/assets/embed/framework/types/router.d.ts +32 -0
- package/create-fusee-go/internal/assets/embed/framework/types/signal.d.ts +79 -0
- package/create-fusee-go/internal/assets/embed/framework/types/store.d.ts +8 -0
- package/create-fusee-go/internal/assets/templates/Counter.tmpl +26 -0
- package/create-fusee-go/internal/assets/templates/component.tmpl +11 -0
- package/create-fusee-go/internal/assets/templates/components/Loading.tmpl +24 -0
- package/create-fusee-go/internal/assets/templates/index.html.tmpl +15 -0
- package/create-fusee-go/internal/assets/templates/main.tmpl +14 -0
- package/create-fusee-go/internal/assets/templates/package.json.tmpl +14 -0
- package/create-fusee-go/internal/assets/templates/page.tmpl +12 -0
- package/create-fusee-go/internal/assets/templates/pages/about.tmpl +20 -0
- package/create-fusee-go/internal/assets/templates/pages/index.tmpl +22 -0
- package/create-fusee-go/internal/assets/templates/pages/layout.tmpl +18 -0
- package/create-fusee-go/internal/assets/templates/tsconfig.json.tmpl +14 -0
- package/create-fusee-go/internal/assets/templates/vite.config.js.tmpl +18 -0
- package/create-fusee-go/main.go +7 -0
- package/framework/auto-import-preset.js +1 -1
- package/framework/core/compiler.js +252 -249
- package/framework/core/component.js +265 -260
- package/framework/core/directives.js +875 -632
- package/framework/core/evaluator.js +153 -70
- package/framework/core/event-delegation.js +191 -0
- package/framework/core/signal.js +412 -404
- package/framework/index.js +10 -11
- package/framework/router/file-router.js +177 -0
- package/framework/router/router.js +462 -80
- package/framework/types/component.d.ts +0 -4
- package/framework/types/event-delegation.d.ts +32 -0
- package/framework/types/index.d.ts +3 -0
- package/framework/types/router.d.ts +32 -15
- package/framework/types/signal.d.ts +1 -0
- package/index.html +638 -563
- package/package.json +5 -3
- package/tsconfig.json +1 -0
- /package/{framework → create-fusee-go/internal/assets/embed/framework}/bin/create-fusee.js +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { effect, setEffectHook, batch } from './signal.js'
|
|
2
|
+
import { mountTemplate } from './compiler.js'
|
|
3
|
+
|
|
4
|
+
let currentInstance = null
|
|
5
|
+
|
|
6
|
+
setEffectHook(eff => {
|
|
7
|
+
if (currentInstance) currentInstance._effects.push(eff)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export function getCurrentInstance() {
|
|
11
|
+
return currentInstance
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function setCurrentInstance(instance) {
|
|
15
|
+
currentInstance = instance
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function resolveProps(schema, received) {
|
|
19
|
+
const isArray = Array.isArray(schema)
|
|
20
|
+
const resolved = {}
|
|
21
|
+
|
|
22
|
+
const normalizedSchema = {}
|
|
23
|
+
if (isArray) {
|
|
24
|
+
schema.forEach(k => normalizedSchema[k.toLowerCase()] = k)
|
|
25
|
+
} else {
|
|
26
|
+
for (const key of Object.keys(schema)) {
|
|
27
|
+
normalizedSchema[key.toLowerCase()] = key
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (const receivedKey of Object.keys(received)) {
|
|
32
|
+
const schemaKey = isArray
|
|
33
|
+
? schema.find(k => k.toLowerCase() === receivedKey.toLowerCase())
|
|
34
|
+
: normalizedSchema[receivedKey.toLowerCase()]
|
|
35
|
+
|
|
36
|
+
if (!schemaKey) {
|
|
37
|
+
console.warn(`[framework] Unknown prop "${receivedKey}"`)
|
|
38
|
+
continue
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const descriptor = Object.getOwnPropertyDescriptor(received, receivedKey)
|
|
42
|
+
if (descriptor && descriptor.get) {
|
|
43
|
+
Object.defineProperty(resolved, schemaKey, {
|
|
44
|
+
get: descriptor.get,
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true
|
|
47
|
+
})
|
|
48
|
+
} else {
|
|
49
|
+
resolved[schemaKey] = received[receivedKey]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isArray) {
|
|
54
|
+
for (const [key, config] of Object.entries(schema)) {
|
|
55
|
+
if (!(key in resolved)) {
|
|
56
|
+
if (config.required) {
|
|
57
|
+
console.error(`[framework] Required prop "${key}" is missing`)
|
|
58
|
+
}
|
|
59
|
+
if (config.default !== undefined) {
|
|
60
|
+
resolved[key] = typeof config.default === 'function'
|
|
61
|
+
? config.default()
|
|
62
|
+
: config.default
|
|
63
|
+
}
|
|
64
|
+
} else if (config.type) {
|
|
65
|
+
const value = resolved[key]
|
|
66
|
+
const expectedType = config.type.name
|
|
67
|
+
const actualType = typeof value
|
|
68
|
+
const typeMap = { String: 'string', Number: 'number', Boolean: 'boolean' }
|
|
69
|
+
if (typeMap[expectedType] && actualType !== typeMap[expectedType]) {
|
|
70
|
+
console.warn(`[framework] Prop "${key}" expected ${expectedType} but got ${actualType}`)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return resolved
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function createEmit(listeners) {
|
|
80
|
+
return function emit(eventName, ...args) {
|
|
81
|
+
const handler = listeners[eventName]
|
|
82
|
+
if (typeof handler === 'function') {
|
|
83
|
+
batch(() => handler(...args))
|
|
84
|
+
} else if (handler !== undefined) {
|
|
85
|
+
console.warn(`[framework] emit("${eventName}"): listener is not a function`)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function parseSlots(slotHTML) {
|
|
91
|
+
const slots = { default: '' }
|
|
92
|
+
if (!slotHTML || !slotHTML.trim()) return slots
|
|
93
|
+
|
|
94
|
+
const namedSlotRe = /<template\s+slot="([^"]+)"[^>]*>([\s\S]*?)<\/template>/gi
|
|
95
|
+
let remaining = slotHTML
|
|
96
|
+
let match
|
|
97
|
+
|
|
98
|
+
while ((match = namedSlotRe.exec(slotHTML)) !== null) {
|
|
99
|
+
slots[match[1]] = match[2].trim()
|
|
100
|
+
remaining = remaining.replace(match[0], '')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const defaultContent = remaining.trim()
|
|
104
|
+
if (defaultContent) slots.default = defaultContent
|
|
105
|
+
|
|
106
|
+
return slots
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function resolveSlots(template, slots) {
|
|
110
|
+
let result = template.replace(/<slot\s+name="([^"]+)"\s*>[\s\S]*?<\/slot>/gi, (match, name) => {
|
|
111
|
+
return slots[name] ?? ''
|
|
112
|
+
})
|
|
113
|
+
result = result.replace(/<slot\s*>[\s\S]*?<\/slot>/gi, () => {
|
|
114
|
+
return slots.default ?? ''
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
result = result.replace(/<slot\s+name="([^"]+)"\s*\/>/gi, (_, name) => slots[name] ?? '')
|
|
118
|
+
result = result.replace(/<slot\s*\/>/gi, () => slots.default ?? '')
|
|
119
|
+
return result
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function onMount(fn) {
|
|
123
|
+
if (currentInstance) currentInstance._mountHooks.push(fn)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function onUnmount(fn) {
|
|
127
|
+
if (currentInstance) currentInstance._unmountHooks.push(fn)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function defineComponent(options) {
|
|
131
|
+
return function ComponentFactory(props = {}, { listeners = {}, slots = {}, parent = null } = {}) {
|
|
132
|
+
const instance = {
|
|
133
|
+
props: options.props ? resolveProps(options.props, props) : props,
|
|
134
|
+
_mountHooks: [],
|
|
135
|
+
_unmountHooks: [],
|
|
136
|
+
_effects: [],
|
|
137
|
+
_element: null,
|
|
138
|
+
_provides: {},
|
|
139
|
+
_parent: parent,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const emit = createEmit(listeners)
|
|
143
|
+
|
|
144
|
+
currentInstance = instance
|
|
145
|
+
const result = options.setup(instance.props, { emit, slots })
|
|
146
|
+
instance.state = result
|
|
147
|
+
result._instance = instance
|
|
148
|
+
currentInstance = null
|
|
149
|
+
|
|
150
|
+
function render(container) {
|
|
151
|
+
instance._element = container
|
|
152
|
+
|
|
153
|
+
const resolvedTemplate = resolveSlots(result.template, slots)
|
|
154
|
+
|
|
155
|
+
const { effects } = mountTemplate(
|
|
156
|
+
resolvedTemplate,
|
|
157
|
+
container,
|
|
158
|
+
result,
|
|
159
|
+
options.components || {}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
instance._effects.push(...effects)
|
|
163
|
+
for (const hook of instance._mountHooks) hook()
|
|
164
|
+
|
|
165
|
+
return instance
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function unmount() {
|
|
169
|
+
for (const hook of instance._unmountHooks) hook()
|
|
170
|
+
const effects = instance._effects
|
|
171
|
+
for (let i = effects.length - 1; i >= 0; i--) {
|
|
172
|
+
const cleanup = effects[i]
|
|
173
|
+
if (typeof cleanup === 'function') cleanup()
|
|
174
|
+
}
|
|
175
|
+
instance._effects = []
|
|
176
|
+
if (instance._element) {
|
|
177
|
+
instance._element.innerHTML = ''
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return { render, unmount, instance }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function provide(key, value) {
|
|
186
|
+
if (!currentInstance) return
|
|
187
|
+
currentInstance._provides[key] = value
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function inject(key) {
|
|
191
|
+
let parent = currentInstance?._parent
|
|
192
|
+
while (parent) {
|
|
193
|
+
if (key in parent._provides) return parent._provides[key];
|
|
194
|
+
parent = parent._parent;
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function defineAsyncComponent(loaderOrOptions) {
|
|
200
|
+
const options = typeof loaderOrOptions === 'function'
|
|
201
|
+
? { loader: loaderOrOptions }
|
|
202
|
+
: loaderOrOptions
|
|
203
|
+
|
|
204
|
+
return function AsyncComponentFactory(props = {}, { listeners = {}, slots = {}, parent = null } = {}) {
|
|
205
|
+
const instance = {
|
|
206
|
+
props,
|
|
207
|
+
_mountHooks: [],
|
|
208
|
+
_unmountHooks: [],
|
|
209
|
+
_effects: [],
|
|
210
|
+
_element: null,
|
|
211
|
+
_provides: {},
|
|
212
|
+
_parent: parent,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let childApi = null
|
|
216
|
+
let loadingApi = null
|
|
217
|
+
let isUnmounted = false
|
|
218
|
+
|
|
219
|
+
function render(container) {
|
|
220
|
+
instance._element = container
|
|
221
|
+
|
|
222
|
+
if (options.loadingComponent) {
|
|
223
|
+
loadingApi = options.loadingComponent({}, { parent })
|
|
224
|
+
loadingApi.render(container)
|
|
225
|
+
} else {
|
|
226
|
+
container.innerHTML = '<!-- async component boundary -->'
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
Promise.resolve(options.loader())
|
|
230
|
+
.then(comp => {
|
|
231
|
+
if (isUnmounted) return
|
|
232
|
+
let ComponentFn = comp.default || comp
|
|
233
|
+
|
|
234
|
+
if (typeof ComponentFn === 'object' && ComponentFn !== null) {
|
|
235
|
+
ComponentFn = Object.values(ComponentFn).find(v => typeof v === 'function') || ComponentFn
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (loadingApi) {
|
|
239
|
+
loadingApi.unmount()
|
|
240
|
+
loadingApi = null
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
childApi = ComponentFn(props, { listeners, slots, parent })
|
|
244
|
+
|
|
245
|
+
container.innerHTML = ''
|
|
246
|
+
childApi.render(container)
|
|
247
|
+
})
|
|
248
|
+
.catch(err => {
|
|
249
|
+
console.error('[framework] Failed to load async component:', err)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return instance
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function unmount() {
|
|
256
|
+
isUnmounted = true
|
|
257
|
+
if (loadingApi) loadingApi.unmount()
|
|
258
|
+
if (childApi) childApi.unmount()
|
|
259
|
+
if (instance._element && !childApi && !loadingApi) {
|
|
260
|
+
instance._element.innerHTML = ''
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return { render, unmount, instance }
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getCurrentInstance } from './component.js'
|
|
2
|
+
|
|
3
|
+
export function defineComposable(fn) {
|
|
4
|
+
const composable = function (...args) {
|
|
5
|
+
return fn(...args)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
composable._isComposable = true
|
|
9
|
+
|
|
10
|
+
Object.defineProperty(composable, 'name', {
|
|
11
|
+
value: fn.name || 'composable',
|
|
12
|
+
configurable: true
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
return composable
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function assertSetupContext(name) {
|
|
19
|
+
const instance = getCurrentInstance()
|
|
20
|
+
if (!instance) {
|
|
21
|
+
console.warn(
|
|
22
|
+
`[framework] ${name ? name + ' ' : ''}composable was called outside of setup(). ` +
|
|
23
|
+
`Lifecycle hooks (onMount, onUnmount) and injections will not work.`
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
return instance
|
|
27
|
+
}
|