pulse-js-framework 1.4.8 → 1.4.9

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/types/hmr.d.ts ADDED
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Pulse Framework - HMR (Hot Module Replacement) Type Definitions
3
+ * @module pulse-js-framework/runtime/hmr
4
+ */
5
+
6
+ import { Pulse, PulseOptions } from './pulse';
7
+
8
+ /**
9
+ * HMR Context interface for state preservation and effect cleanup
10
+ */
11
+ export interface HMRContext {
12
+ /**
13
+ * Persistent data storage across HMR updates.
14
+ * Values stored here survive module reloads.
15
+ */
16
+ data: Record<string, unknown>;
17
+
18
+ /**
19
+ * Create a pulse with state preservation across HMR updates.
20
+ * If a value exists from a previous module load, it's restored.
21
+ *
22
+ * @param key - Unique key for this pulse within the module
23
+ * @param initialValue - Initial value (used on first load only)
24
+ * @param options - Pulse options (equals function, etc.)
25
+ * @returns A pulse instance with preserved state
26
+ *
27
+ * @example
28
+ * const count = hmr.preservePulse('count', 0);
29
+ * const todos = hmr.preservePulse('todos', [], { equals: deepEquals });
30
+ */
31
+ preservePulse<T>(key: string, initialValue: T, options?: PulseOptions<T>): Pulse<T>;
32
+
33
+ /**
34
+ * Execute code with module tracking enabled.
35
+ * Effects created within this callback will be registered
36
+ * for automatic cleanup during HMR.
37
+ *
38
+ * @param callback - Code to execute with tracking
39
+ * @returns The return value of the callback
40
+ *
41
+ * @example
42
+ * hmr.setup(() => {
43
+ * effect(() => {
44
+ * document.title = `Count: ${count.get()}`;
45
+ * });
46
+ * });
47
+ */
48
+ setup<T>(callback: () => T): T;
49
+
50
+ /**
51
+ * Register a callback to run when the module accepts an HMR update.
52
+ * Call without arguments to auto-accept updates.
53
+ *
54
+ * @param callback - Optional callback for custom handling
55
+ *
56
+ * @example
57
+ * hmr.accept(); // Auto-accept
58
+ * hmr.accept(() => console.log('Module updated!'));
59
+ */
60
+ accept(callback?: () => void): void;
61
+
62
+ /**
63
+ * Register a callback to run before the module is replaced.
64
+ * Use this for custom cleanup logic.
65
+ *
66
+ * @param callback - Cleanup callback
67
+ *
68
+ * @example
69
+ * hmr.dispose(() => {
70
+ * socket.close();
71
+ * clearInterval(timer);
72
+ * });
73
+ */
74
+ dispose(callback: () => void): void;
75
+ }
76
+
77
+ /**
78
+ * Create an HMR context for a module.
79
+ * Provides utilities for state preservation and effect cleanup during HMR.
80
+ *
81
+ * In production or non-HMR environments, returns a no-op context
82
+ * that works normally but without HMR-specific behavior.
83
+ *
84
+ * @param moduleId - The module identifier (typically import.meta.url)
85
+ * @returns HMR context with preservation utilities
86
+ *
87
+ * @example
88
+ * import { createHMRContext } from 'pulse-js-framework/runtime/hmr';
89
+ *
90
+ * const hmr = createHMRContext(import.meta.url);
91
+ *
92
+ * // Preserve state across HMR
93
+ * const todos = hmr.preservePulse('todos', []);
94
+ * const filter = hmr.preservePulse('filter', 'all');
95
+ *
96
+ * // Setup effects with automatic cleanup
97
+ * hmr.setup(() => {
98
+ * effect(() => {
99
+ * document.title = `${todos.get().length} todos`;
100
+ * });
101
+ * });
102
+ *
103
+ * // Accept HMR updates
104
+ * hmr.accept();
105
+ */
106
+ export function createHMRContext(moduleId: string): HMRContext;
107
+
108
+ declare const hmr: {
109
+ createHMRContext: typeof createHMRContext;
110
+ };
111
+
112
+ export default hmr;
package/types/index.d.ts CHANGED
@@ -90,8 +90,15 @@ export {
90
90
  LinkOptions,
91
91
  MatchedRoute,
92
92
  Router,
93
+ MiddlewareContext,
94
+ MiddlewareFn,
95
+ LazyOptions,
96
+ LazyRouteHandler,
97
+ RouteContext,
93
98
  createRouter,
94
- simpleRouter
99
+ simpleRouter,
100
+ lazy,
101
+ preload
95
102
  } from './router';
96
103
 
97
104
  // Store
@@ -137,3 +144,20 @@ export {
137
144
  logger,
138
145
  loggers
139
146
  } from './logger';
147
+
148
+ // HMR (Hot Module Replacement)
149
+ export {
150
+ HMRContext,
151
+ createHMRContext
152
+ } from './hmr';
153
+
154
+ // Source Maps (Compiler)
155
+ export {
156
+ Position,
157
+ Mapping,
158
+ SourceMapV3,
159
+ OriginalPosition,
160
+ SourceMapGenerator,
161
+ SourceMapConsumer,
162
+ encodeVLQ
163
+ } from './sourcemap';
package/types/router.d.ts CHANGED
@@ -69,12 +69,57 @@ export interface Routes {
69
69
  [path: string]: RouteHandler | RouteDefinition;
70
70
  }
71
71
 
72
+ // =============================================================================
73
+ // Middleware Types
74
+ // =============================================================================
75
+
76
+ /** Middleware context passed to each middleware function */
77
+ export interface MiddlewareContext {
78
+ /** Target route */
79
+ to: NavigationTarget;
80
+ /** Source route */
81
+ from: NavigationTarget;
82
+ /** Shared metadata between middlewares */
83
+ meta: Record<string, unknown>;
84
+ /** Redirect to another path */
85
+ redirect(path: string): void;
86
+ /** Abort navigation */
87
+ abort(): void;
88
+ }
89
+
90
+ /** Middleware function */
91
+ export type MiddlewareFn = (
92
+ ctx: MiddlewareContext,
93
+ next: () => Promise<void>
94
+ ) => void | Promise<void>;
95
+
96
+ // =============================================================================
97
+ // Lazy Loading Types
98
+ // =============================================================================
99
+
100
+ /** Lazy loading options */
101
+ export interface LazyOptions {
102
+ /** Loading component shown while loading */
103
+ loading?: () => Node;
104
+ /** Error component shown on failure */
105
+ error?: (err: Error) => Node;
106
+ /** Timeout in milliseconds (default: 10000) */
107
+ timeout?: number;
108
+ /** Delay before showing loading component (default: 200) */
109
+ delay?: number;
110
+ }
111
+
112
+ /** Lazy route handler */
113
+ export type LazyRouteHandler = (ctx: RouteContext) => Node;
114
+
72
115
  /** Router options */
73
116
  export interface RouterOptions {
74
117
  routes?: Routes;
75
118
  mode?: 'history' | 'hash';
76
119
  base?: string;
77
120
  scrollBehavior?: ScrollBehaviorFn;
121
+ /** Middleware functions */
122
+ middleware?: MiddlewareFn[];
78
123
  }
79
124
 
80
125
  /** Navigation options */
@@ -84,6 +129,15 @@ export interface NavigateOptions {
84
129
  state?: unknown;
85
130
  }
86
131
 
132
+ /** Route context passed to route handlers */
133
+ export interface RouteContext {
134
+ params: RouteParams;
135
+ query: QueryParams;
136
+ path: string;
137
+ navigate: Router['navigate'];
138
+ router: Router;
139
+ }
140
+
87
141
  /** Link options */
88
142
  export interface LinkOptions {
89
143
  exact?: boolean;
@@ -141,6 +195,12 @@ export interface Router {
141
195
  /** Go to specific history entry */
142
196
  go(delta: number): void;
143
197
 
198
+ /**
199
+ * Add middleware dynamically
200
+ * @returns Unregister function
201
+ */
202
+ use(middleware: MiddlewareFn): () => void;
203
+
144
204
  /**
145
205
  * Add global before-navigation guard
146
206
  * @returns Unregister function
@@ -195,3 +255,32 @@ export declare function createRouter(options?: RouterOptions): Router;
195
255
  * Quick router setup (creates, starts, and mounts)
196
256
  */
197
257
  export declare function simpleRouter(routes: Routes, target?: string): Router;
258
+
259
+ /**
260
+ * Create a lazy-loaded route handler
261
+ * Wraps a dynamic import with loading states and error handling
262
+ *
263
+ * @example
264
+ * const routes = {
265
+ * '/dashboard': lazy(() => import('./Dashboard.js')),
266
+ * '/settings': lazy(() => import('./Settings.js'), {
267
+ * loading: () => el('div.spinner', 'Loading...'),
268
+ * error: (err) => el('div.error', `Failed: ${err.message}`),
269
+ * timeout: 5000
270
+ * })
271
+ * };
272
+ */
273
+ export declare function lazy(
274
+ importFn: () => Promise<{ default: RouteHandler | (() => Node) }>,
275
+ options?: LazyOptions
276
+ ): LazyRouteHandler;
277
+
278
+ /**
279
+ * Preload a lazy component without rendering
280
+ * Useful for prefetching on hover or when likely to navigate
281
+ *
282
+ * @example
283
+ * const DashboardLazy = lazy(() => import('./Dashboard.js'));
284
+ * link.addEventListener('mouseenter', () => preload(DashboardLazy));
285
+ */
286
+ export declare function preload(lazyHandler: LazyRouteHandler): Promise<void>;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Pulse Framework - Source Map Type Definitions
3
+ * @module pulse-js-framework/compiler/sourcemap
4
+ */
5
+
6
+ /** Source map position */
7
+ export interface Position {
8
+ line: number;
9
+ column: number;
10
+ }
11
+
12
+ /** Source map mapping */
13
+ export interface Mapping {
14
+ generated: Position;
15
+ original?: Position;
16
+ source?: string;
17
+ name?: string;
18
+ }
19
+
20
+ /** V3 Source Map format */
21
+ export interface SourceMapV3 {
22
+ version: 3;
23
+ file: string;
24
+ sourceRoot: string;
25
+ sources: string[];
26
+ sourcesContent: (string | null)[];
27
+ names: string[];
28
+ mappings: string;
29
+ }
30
+
31
+ /** Original position result from consumer */
32
+ export interface OriginalPosition {
33
+ source: string;
34
+ line: number;
35
+ column: number;
36
+ name: string | null;
37
+ }
38
+
39
+ /**
40
+ * Source Map Generator
41
+ * Generates V3 source maps for compiled .pulse files
42
+ */
43
+ export declare class SourceMapGenerator {
44
+ /**
45
+ * Create a new source map generator
46
+ * @param options - Generator options
47
+ */
48
+ constructor(options?: {
49
+ file?: string;
50
+ sourceRoot?: string;
51
+ });
52
+
53
+ /**
54
+ * Add a source file
55
+ * @param source - Source file path
56
+ * @param content - Source file content (optional, for inline sources)
57
+ * @returns Source index
58
+ */
59
+ addSource(source: string, content?: string | null): number;
60
+
61
+ /**
62
+ * Add a name (identifier) to the names array
63
+ * @param name - Identifier name
64
+ * @returns Name index
65
+ */
66
+ addName(name: string): number;
67
+
68
+ /**
69
+ * Add a mapping between generated and original positions
70
+ * @param mapping - Mapping information
71
+ */
72
+ addMapping(mapping: Mapping): void;
73
+
74
+ /**
75
+ * Generate the source map object
76
+ * @returns V3 source map object
77
+ */
78
+ toJSON(): SourceMapV3;
79
+
80
+ /**
81
+ * Generate source map as JSON string
82
+ */
83
+ toString(): string;
84
+
85
+ /**
86
+ * Generate inline source map comment
87
+ * @returns Comment with base64 encoded source map
88
+ */
89
+ toComment(): string;
90
+
91
+ /**
92
+ * Generate external source map URL comment
93
+ * @param url - URL to source map file
94
+ */
95
+ static toURLComment(url: string): string;
96
+ }
97
+
98
+ /**
99
+ * Source Map Consumer
100
+ * Parse and query source maps for error stack trace translation
101
+ */
102
+ export declare class SourceMapConsumer {
103
+ /**
104
+ * Create a new source map consumer
105
+ * @param sourceMap - Source map object or JSON string
106
+ */
107
+ constructor(sourceMap: SourceMapV3 | string);
108
+
109
+ /**
110
+ * Decode VLQ string to numbers
111
+ * @param str - VLQ encoded string
112
+ */
113
+ static decodeVLQ(str: string): number[];
114
+
115
+ /**
116
+ * Get original position for a generated position
117
+ * @param position - Generated position
118
+ * @returns Original position or null if not found
119
+ */
120
+ originalPositionFor(position: Position): OriginalPosition | null;
121
+ }
122
+
123
+ /**
124
+ * Encode a number as VLQ base64
125
+ */
126
+ export declare function encodeVLQ(value: number): string;