@liteforge/runtime 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SchildW3rk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # @liteforge/runtime
2
+
3
+ DOM runtime for LiteForge: components, context, lifecycle, and control flow.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @liteforge/runtime @liteforge/core
9
+ ```
10
+
11
+ Peer dependency: `@liteforge/core >= 0.1.0`
12
+
13
+ ## Overview
14
+
15
+ `@liteforge/runtime` provides the component model, app creation, context system, and control flow primitives for LiteForge applications.
16
+
17
+ ## API
18
+
19
+ ### createApp
20
+
21
+ Creates and mounts a LiteForge application.
22
+
23
+ ```tsx
24
+ import { createApp } from '@liteforge/runtime'
25
+ import { App } from './App'
26
+
27
+ const app = createApp({
28
+ root: '#app', // CSS selector or HTMLElement
29
+ router: myRouter, // Optional: router instance
30
+ stores: [userStore], // Optional: stores to register
31
+ plugins: [devtools()], // Optional: plugins
32
+ })
33
+
34
+ app.mount(App)
35
+ ```
36
+
37
+ ### createComponent
38
+
39
+ Creates a component with lifecycle hooks and async data loading.
40
+
41
+ ```tsx
42
+ import { createComponent } from '@liteforge/runtime'
43
+ import { signal } from '@liteforge/core'
44
+
45
+ const UserProfile = createComponent({
46
+ // Define props with validation
47
+ props: {
48
+ userId: { type: String, required: true },
49
+ showEmail: { type: Boolean, default: false }
50
+ },
51
+
52
+ // Synchronous setup (runs immediately)
53
+ setup({ props, use }) {
54
+ const isEditing = signal(false)
55
+ return { isEditing }
56
+ },
57
+
58
+ // Async data loading (component waits for this)
59
+ async load({ props, setup, use }) {
60
+ const api = use('api')
61
+ const user = await api.get(`/users/${props.userId}`)
62
+ return { user }
63
+ },
64
+
65
+ // Shown while load() is pending
66
+ placeholder: () => <div class="skeleton" />,
67
+
68
+ // Shown if load() throws
69
+ error: ({ error, retry }) => (
70
+ <div>
71
+ <p>Error: {error.message}</p>
72
+ <button onclick={retry}>Retry</button>
73
+ </div>
74
+ ),
75
+
76
+ // Main render function
77
+ component: ({ props, data, setup }) => (
78
+ <div>
79
+ <h1>{data.user.name}</h1>
80
+ {() => props.showEmail && <p>{data.user.email}</p>}
81
+ </div>
82
+ ),
83
+
84
+ // After DOM insertion
85
+ mounted({ el }) {
86
+ el.classList.add('fade-in')
87
+ },
88
+
89
+ // Before removal
90
+ destroyed() {
91
+ console.log('Cleanup')
92
+ }
93
+ })
94
+ ```
95
+
96
+ **Lifecycle Order:** `setup()` → `placeholder` renders → `load()` → `component` renders → `mounted()` → `destroyed()`
97
+
98
+ ### use
99
+
100
+ Access registered services, stores, and the router.
101
+
102
+ ```tsx
103
+ import { use } from '@liteforge/runtime'
104
+
105
+ // Inside a component
106
+ const MyComponent = createComponent({
107
+ component: () => {
108
+ const router = use('router')
109
+ const userStore = use('users')
110
+
111
+ return <button onclick={() => router.navigate('/')}>Home</button>
112
+ }
113
+ })
114
+ ```
115
+
116
+ ### Control Flow
117
+
118
+ #### Show
119
+
120
+ Conditionally renders content.
121
+
122
+ ```tsx
123
+ import { Show } from '@liteforge/runtime'
124
+
125
+ <Show when={() => isLoggedIn()} fallback={<LoginPrompt />}>
126
+ <Dashboard />
127
+ </Show>
128
+ ```
129
+
130
+ #### For
131
+
132
+ Renders a list of items.
133
+
134
+ ```tsx
135
+ import { For } from '@liteforge/runtime'
136
+
137
+ <For each={() => items()} fallback={<p>No items</p>}>
138
+ {(item, index) => (
139
+ <li>{index()}: {item.name}</li>
140
+ )}
141
+ </For>
142
+ ```
143
+
144
+ #### Switch / Match
145
+
146
+ Renders the first matching case.
147
+
148
+ ```tsx
149
+ import { Switch, Match } from '@liteforge/runtime'
150
+
151
+ <Switch fallback={<NotFound />}>
152
+ <Match when={() => status() === 'loading'}>
153
+ <Spinner />
154
+ </Match>
155
+ <Match when={() => status() === 'error'}>
156
+ <ErrorMessage />
157
+ </Match>
158
+ <Match when={() => status() === 'success'}>
159
+ <Content />
160
+ </Match>
161
+ </Switch>
162
+ ```
163
+
164
+ #### Dynamic
165
+
166
+ Dynamically renders a component based on a signal.
167
+
168
+ ```tsx
169
+ import { Dynamic } from '@liteforge/runtime'
170
+
171
+ const currentView = signal(HomeView)
172
+
173
+ <Dynamic component={() => currentView()} props={{ user }} />
174
+ ```
175
+
176
+ ### h and Fragment
177
+
178
+ The JSX factory functions (used by the Vite plugin).
179
+
180
+ ```tsx
181
+ import { h, Fragment } from '@liteforge/runtime'
182
+
183
+ // Usually not called directly — JSX compiles to h() calls
184
+ const element = h('div', { class: 'container' },
185
+ h('p', null, 'Hello')
186
+ )
187
+
188
+ // Fragment for multiple root elements
189
+ const items = (
190
+ <>
191
+ <li>One</li>
192
+ <li>Two</li>
193
+ </>
194
+ )
195
+ ```
196
+
197
+ ## Types
198
+
199
+ ```ts
200
+ import type {
201
+ ComponentDefinition,
202
+ ComponentFactory,
203
+ AppConfig,
204
+ AppInstance,
205
+ Plugin,
206
+ ShowProps,
207
+ ForProps,
208
+ SwitchProps,
209
+ MatchProps,
210
+ DynamicProps
211
+ } from '@liteforge/runtime'
212
+ ```
213
+
214
+ ## License
215
+
216
+ MIT
package/dist/app.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * LiteForge createApp
3
+ *
4
+ * Central app bootstrap: mounts root component, initializes stores,
5
+ * sets up context, router, plugins, and debug utilities.
6
+ */
7
+ import type { AppConfig, AppInstance } from './types.js';
8
+ /**
9
+ * Create and bootstrap a LiteForge application.
10
+ *
11
+ * This is an async function that:
12
+ * 1. Resolves the target element
13
+ * 2. Builds the app context (custom context + router + stores)
14
+ * 3. Runs plugin beforeInit hooks
15
+ * 4. Initializes stores (calls initialize() if present)
16
+ * 5. Starts the router (if present)
17
+ * 6. Mounts the root component
18
+ * 7. Runs plugin afterMount hooks
19
+ * 8. Sets up debug utilities (if debug mode)
20
+ * 9. Calls onReady callback
21
+ *
22
+ * @param config - Application configuration
23
+ * @returns Promise resolving to the app instance
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const app = await createApp({
28
+ * root: App,
29
+ * target: '#app',
30
+ * router: createAppRouter(),
31
+ * stores: [authStore, uiStore],
32
+ * context: { api: createApiClient() },
33
+ * debug: true,
34
+ * });
35
+ * ```
36
+ */
37
+ export declare function createApp(config: AppConfig): Promise<AppInstance>;
38
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAIZ,MAAM,YAAY,CAAC;AAoBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAuPvE"}
package/dist/app.js ADDED
@@ -0,0 +1,266 @@
1
+ /**
2
+ * LiteForge createApp
3
+ *
4
+ * Central app bootstrap: mounts root component, initializes stores,
5
+ * sets up context, router, plugins, and debug utilities.
6
+ */
7
+ import { initAppContext, clearContext, use } from './context.js';
8
+ import { isComponentFactory } from './component.js';
9
+ // ============================================================================
10
+ // createApp Implementation
11
+ // ============================================================================
12
+ /**
13
+ * Create and bootstrap a LiteForge application.
14
+ *
15
+ * This is an async function that:
16
+ * 1. Resolves the target element
17
+ * 2. Builds the app context (custom context + router + stores)
18
+ * 3. Runs plugin beforeInit hooks
19
+ * 4. Initializes stores (calls initialize() if present)
20
+ * 5. Starts the router (if present)
21
+ * 6. Mounts the root component
22
+ * 7. Runs plugin afterMount hooks
23
+ * 8. Sets up debug utilities (if debug mode)
24
+ * 9. Calls onReady callback
25
+ *
26
+ * @param config - Application configuration
27
+ * @returns Promise resolving to the app instance
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const app = await createApp({
32
+ * root: App,
33
+ * target: '#app',
34
+ * router: createAppRouter(),
35
+ * stores: [authStore, uiStore],
36
+ * context: { api: createApiClient() },
37
+ * debug: true,
38
+ * });
39
+ * ```
40
+ */
41
+ export async function createApp(config) {
42
+ let rootInstance = null;
43
+ let rootNode = null;
44
+ let targetElement = null;
45
+ let isMounted = false;
46
+ const appContext = {};
47
+ const storesMap = {};
48
+ // Determine debug mode (auto-detect from Vite's import.meta.env.DEV)
49
+ const isDebug = config.debug ??
50
+ (typeof globalThis !== 'undefined' &&
51
+ globalThis.__DEV__ === true);
52
+ try {
53
+ // ========================================
54
+ // 1. Resolve target element
55
+ // ========================================
56
+ if (typeof config.target === 'string') {
57
+ targetElement = document.querySelector(config.target);
58
+ if (!targetElement) {
59
+ throw new Error(`Target element "${config.target}" not found`);
60
+ }
61
+ }
62
+ else {
63
+ targetElement = config.target;
64
+ }
65
+ // ========================================
66
+ // 2. Build app context
67
+ // ========================================
68
+ // 2a. Custom context values
69
+ if (config.context) {
70
+ Object.assign(appContext, config.context);
71
+ }
72
+ // 2b. Router
73
+ if (config.router) {
74
+ appContext.router = config.router;
75
+ }
76
+ // 2c. Stores - register under $name and with store: prefix
77
+ if (config.stores) {
78
+ for (const store of config.stores) {
79
+ storesMap[store.$name] = store;
80
+ appContext[`store:${store.$name}`] = store;
81
+ // Also register directly by name for convenience
82
+ appContext[store.$name] = store;
83
+ }
84
+ }
85
+ // 2d. Plugin provide values
86
+ if (config.plugins) {
87
+ for (const plugin of config.plugins) {
88
+ if (plugin.provide) {
89
+ Object.assign(appContext, plugin.provide);
90
+ }
91
+ }
92
+ }
93
+ // ========================================
94
+ // 3. Plugin beforeInit hooks
95
+ // ========================================
96
+ if (config.plugins) {
97
+ for (const plugin of config.plugins) {
98
+ if (plugin.beforeInit) {
99
+ await plugin.beforeInit({ context: appContext });
100
+ }
101
+ }
102
+ }
103
+ // Initialize app-level context (makes use() work)
104
+ initAppContext(appContext);
105
+ // ========================================
106
+ // 4. Initialize stores
107
+ // ========================================
108
+ if (config.stores) {
109
+ for (const store of config.stores) {
110
+ if ('initialize' in store && typeof store.initialize === 'function') {
111
+ if (isDebug) {
112
+ console.log(`[LiteForge] Initializing store: ${store.$name}`);
113
+ }
114
+ await store.initialize();
115
+ }
116
+ }
117
+ }
118
+ // ========================================
119
+ // 5. Start router
120
+ // ========================================
121
+ if (config.router && 'start' in config.router && typeof config.router.start === 'function') {
122
+ if (isDebug) {
123
+ console.log('[LiteForge] Starting router...');
124
+ }
125
+ await config.router.start();
126
+ }
127
+ // ========================================
128
+ // 6. Mount root component
129
+ // ========================================
130
+ const rootConfig = config.root;
131
+ if (isComponentFactory(rootConfig)) {
132
+ // It's a ComponentFactory from createComponent()
133
+ rootInstance = rootConfig({});
134
+ rootInstance.mount(targetElement);
135
+ }
136
+ else {
137
+ // It's a simple render function () => Node
138
+ rootNode = rootConfig();
139
+ targetElement.appendChild(rootNode);
140
+ }
141
+ isMounted = true;
142
+ // ========================================
143
+ // 7. Plugin afterMount hooks
144
+ // ========================================
145
+ // Create app instance first so plugins can use it
146
+ // Note: We build the object conditionally to satisfy exactOptionalPropertyTypes
147
+ const app = Object.assign({
148
+ unmount,
149
+ use: createAppUse(appContext),
150
+ stores: storesMap,
151
+ }, config.router ? { router: config.router } : {});
152
+ if (config.plugins) {
153
+ for (const plugin of config.plugins) {
154
+ if (plugin.afterMount) {
155
+ await plugin.afterMount(app);
156
+ }
157
+ }
158
+ }
159
+ // ========================================
160
+ // 8. Debug utilities
161
+ // ========================================
162
+ if (isDebug && typeof window !== 'undefined') {
163
+ const debugUtils = {
164
+ router: config.router,
165
+ stores: storesMap,
166
+ snapshot: () => {
167
+ const result = {};
168
+ for (const [name, store] of Object.entries(storesMap)) {
169
+ result[name] = store.$snapshot();
170
+ }
171
+ return result;
172
+ },
173
+ unmount: () => app.unmount(),
174
+ context: appContext,
175
+ };
176
+ Object.defineProperty(window, '$lf', {
177
+ value: debugUtils,
178
+ configurable: true,
179
+ writable: false,
180
+ });
181
+ console.log('='.repeat(50));
182
+ console.log('[LiteForge] Application started in debug mode');
183
+ console.log(' $lf.stores — Store instances');
184
+ console.log(' $lf.router — Router instance');
185
+ console.log(' $lf.snapshot()— Full state snapshot');
186
+ console.log(' $lf.context — App context');
187
+ console.log(' $lf.unmount() — Unmount app');
188
+ console.log('='.repeat(50));
189
+ }
190
+ // ========================================
191
+ // 9. onReady callback
192
+ // ========================================
193
+ if (config.onReady) {
194
+ config.onReady(app);
195
+ }
196
+ return app;
197
+ }
198
+ catch (error) {
199
+ // Handle bootstrap errors
200
+ const err = error instanceof Error ? error : new Error(String(error));
201
+ if (config.onError) {
202
+ config.onError(err);
203
+ }
204
+ // Re-throw so the promise rejects
205
+ throw err;
206
+ }
207
+ // ========================================
208
+ // Internal Functions
209
+ // ========================================
210
+ function unmount() {
211
+ if (!isMounted)
212
+ return;
213
+ // Plugin beforeUnmount hooks
214
+ if (config.plugins) {
215
+ for (const plugin of config.plugins) {
216
+ if (plugin.beforeUnmount) {
217
+ const appForPlugin = Object.assign({
218
+ unmount,
219
+ use: createAppUse(appContext),
220
+ stores: storesMap,
221
+ }, config.router ? { router: config.router } : {});
222
+ plugin.beforeUnmount(appForPlugin);
223
+ }
224
+ }
225
+ }
226
+ // Unmount root component
227
+ if (rootInstance) {
228
+ rootInstance.unmount();
229
+ rootInstance = null;
230
+ }
231
+ // Remove simple render function node
232
+ if (rootNode && rootNode.parentNode) {
233
+ rootNode.parentNode.removeChild(rootNode);
234
+ rootNode = null;
235
+ }
236
+ // Clear target element
237
+ if (targetElement) {
238
+ targetElement.innerHTML = '';
239
+ }
240
+ // Stop router
241
+ if (config.router && 'stop' in config.router && typeof config.router.stop === 'function') {
242
+ config.router.stop();
243
+ }
244
+ // Remove debug utilities from window
245
+ if (typeof window !== 'undefined' && '$lf' in window) {
246
+ delete window.$lf;
247
+ }
248
+ // Clear context
249
+ clearContext();
250
+ isMounted = false;
251
+ }
252
+ }
253
+ /**
254
+ * Create a bound use() function for the app instance.
255
+ * This allows accessing context from outside components.
256
+ */
257
+ function createAppUse(appContext) {
258
+ return function appUse(key) {
259
+ if (key in appContext) {
260
+ return appContext[key];
261
+ }
262
+ // Fall back to global use() which checks the context stack
263
+ return use(key);
264
+ };
265
+ }
266
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * LiteForge createComponent
3
+ *
4
+ * The central factory for creating reactive components with full lifecycle support.
5
+ *
6
+ * Lifecycle Flow:
7
+ * 1. setup() - Synchronous, create local signals
8
+ * 2. placeholder - Shown immediately (if load exists)
9
+ * 3. load() - Async data fetching
10
+ * 4. component() - Render (only when load resolved)
11
+ * 5. mounted() - After DOM insertion
12
+ * 6. destroyed() - On unmount
13
+ */
14
+ import type { ComponentDefinition, ComponentFactory, PropDefinition, InputPropsFromSchema, Simplify } from './types.js';
15
+ /**
16
+ * Create a component factory from a component definition.
17
+ *
18
+ * @param definition - The component definition object
19
+ * @returns A component factory function
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const MyComponent = createComponent({
24
+ * props: { name: { type: String, required: true } },
25
+ * setup({ props }) {
26
+ * const count = signal(0);
27
+ * return { count };
28
+ * },
29
+ * component({ props, setup }) {
30
+ * return <div>Hello {props.name}, count: {setup.count()}</div>;
31
+ * },
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function createComponent<Schema extends Record<string, PropDefinition<unknown>>, P extends {
36
+ [K in keyof Schema]: Schema[K] extends PropDefinition<infer T> ? T : never;
37
+ }, D = undefined, S = undefined>(definition: ComponentDefinition<P, D, S> & {
38
+ props: Schema;
39
+ }): ComponentFactory<P, Simplify<InputPropsFromSchema<Schema, P>>>;
40
+ export declare function createComponent<P extends Record<string, unknown> = Record<string, unknown>, D = undefined, S = undefined>(definition: ComponentDefinition<P, D, S>): ComponentFactory<P, P>;
41
+ /**
42
+ * Check if a value is a LiteForge component factory.
43
+ */
44
+ export declare function isComponentFactory(value: unknown): value is ComponentFactory<Record<string, unknown>>;
45
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAEhB,cAAc,EACd,oBAAoB,EACpB,QAAQ,EACT,MAAM,YAAY,CAAC;AAuBpB;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,wBAAgB,eAAe,CAC7B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,EACtD,CAAC,SAAS;KAAG,CAAC,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CAAE,EACxF,CAAC,GAAG,SAAS,EACb,CAAC,GAAG,SAAS,EAEb,UAAU,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D,gBAAgB,CAAC,CAAC,EAAE,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAGlE,wBAAgB,eAAe,CAC7B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,CAAC,GAAG,SAAS,EACb,CAAC,GAAG,SAAS,EACb,UAAU,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAkTpE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAKrG"}