pulse-js-framework 1.7.32 → 1.7.37

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.
@@ -0,0 +1,618 @@
1
+ /**
2
+ * Pulse Framework - Error Classes Type Definitions
3
+ *
4
+ * Structured error handling for the framework with source location tracking,
5
+ * code snippet formatting, and helpful suggestions.
6
+ *
7
+ * @module pulse-js-framework/core/errors
8
+ */
9
+
10
+ // ============================================================================
11
+ // Error Options
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Options for constructing a PulseError
16
+ */
17
+ export interface PulseErrorOptions {
18
+ /** Line number where error occurred */
19
+ line?: number;
20
+ /** Column number where error occurred */
21
+ column?: number;
22
+ /** Source file path */
23
+ file?: string;
24
+ /** Error code for documentation lookup */
25
+ code?: string;
26
+ /** Original source code */
27
+ source?: string;
28
+ /** Helpful suggestion to fix the error */
29
+ suggestion?: string;
30
+ }
31
+
32
+ /**
33
+ * Options for constructing a ParserError
34
+ */
35
+ export interface ParserErrorOptions extends PulseErrorOptions {
36
+ /** The problematic token */
37
+ token?: unknown;
38
+ }
39
+
40
+ /**
41
+ * Options for constructing a ClientError
42
+ */
43
+ export interface ClientErrorOptions {
44
+ /** Error code */
45
+ code?: string;
46
+ /** Error context description */
47
+ context?: string;
48
+ /** Custom suggestion (overrides default from suggestions map) */
49
+ suggestion?: string;
50
+ }
51
+
52
+ /**
53
+ * Options for the createErrorMessage utility
54
+ */
55
+ export interface ErrorMessageOptions {
56
+ /** Error code (e.g., 'COMPUTED_SET') */
57
+ code: string;
58
+ /** Main error message */
59
+ message: string;
60
+ /** What the user was trying to do */
61
+ context?: string;
62
+ /** How to fix the error */
63
+ suggestion?: string;
64
+ /** Additional key-value details */
65
+ details?: Record<string, unknown>;
66
+ }
67
+
68
+ /**
69
+ * Configuration for createClientErrorClass factory
70
+ */
71
+ export interface ClientErrorClassConfig {
72
+ /** Error class name (e.g., 'HttpError') */
73
+ name: string;
74
+ /** Default error code when none provided */
75
+ defaultCode: string;
76
+ /** Instance marker property name (e.g., 'isHttpError') */
77
+ markerProperty: string;
78
+ /** Error code to suggestion string mapping */
79
+ suggestions?: Record<string, string>;
80
+ /** Error codes to create isXxx() instance methods for */
81
+ codeMethods?: string[];
82
+ /** Extra properties to copy from constructor options */
83
+ additionalProperties?: string[];
84
+ }
85
+
86
+ /**
87
+ * JSON representation of a PulseError
88
+ */
89
+ export interface PulseErrorJSON {
90
+ name: string;
91
+ message: string;
92
+ line: number | null;
93
+ column: number | null;
94
+ file: string | null;
95
+ code: string;
96
+ suggestion: string | null;
97
+ }
98
+
99
+ // ============================================================================
100
+ // Base Error Class
101
+ // ============================================================================
102
+
103
+ /**
104
+ * Base error class for all Pulse framework errors.
105
+ * Provides source location tracking and code snippet formatting.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * const error = new PulseError('Something went wrong', {
110
+ * line: 10,
111
+ * column: 5,
112
+ * file: 'App.pulse',
113
+ * code: 'CUSTOM_ERROR',
114
+ * suggestion: 'Check your syntax'
115
+ * });
116
+ * console.error(error.formatWithSnippet(sourceCode));
117
+ * ```
118
+ */
119
+ export declare class PulseError extends Error {
120
+ readonly name: string;
121
+
122
+ /** Line number where the error occurred */
123
+ readonly line: number | null;
124
+
125
+ /** Column number where the error occurred */
126
+ readonly column: number | null;
127
+
128
+ /** Source file path */
129
+ readonly file: string | null;
130
+
131
+ /** Error code for documentation lookup */
132
+ readonly code: string;
133
+
134
+ /** Original source code */
135
+ readonly source: string | null;
136
+
137
+ /** Helpful suggestion to fix the error */
138
+ readonly suggestion: string | null;
139
+
140
+ /**
141
+ * @param message - Error message
142
+ * @param options - Error options with source location and context
143
+ */
144
+ constructor(message: string, options?: PulseErrorOptions);
145
+
146
+ /**
147
+ * Format the error with a code snippet showing surrounding context lines.
148
+ *
149
+ * @param source - Source code to use (overrides this.source)
150
+ * @param contextLines - Number of lines to show before/after error (default: 2)
151
+ * @returns Formatted error string with code snippet, location, and suggestion
152
+ */
153
+ formatWithSnippet(source?: string | null, contextLines?: number): string;
154
+
155
+ /**
156
+ * Format error without source code context.
157
+ * Includes file location, suggestion, and documentation URL.
158
+ *
159
+ * @returns Formatted error message
160
+ */
161
+ format(): string;
162
+
163
+ /**
164
+ * Convert to plain object for JSON serialization.
165
+ *
166
+ * @returns Plain object representation
167
+ */
168
+ toJSON(): PulseErrorJSON;
169
+ }
170
+
171
+ // ============================================================================
172
+ // Compiler Errors
173
+ // ============================================================================
174
+
175
+ /**
176
+ * Base class for all compilation errors.
177
+ * Default code: 'COMPILE_ERROR'
178
+ */
179
+ export declare class CompileError extends PulseError {
180
+ readonly name: 'CompileError';
181
+
182
+ constructor(message: string, options?: PulseErrorOptions);
183
+ }
184
+
185
+ /**
186
+ * Error during lexical analysis (tokenization).
187
+ * Default code: 'LEXER_ERROR'
188
+ */
189
+ export declare class LexerError extends CompileError {
190
+ readonly name: 'LexerError';
191
+
192
+ constructor(message: string, options?: PulseErrorOptions);
193
+ }
194
+
195
+ /**
196
+ * Error during parsing (AST construction).
197
+ * Default code: 'PARSER_ERROR'
198
+ */
199
+ export declare class ParserError extends CompileError {
200
+ readonly name: 'ParserError';
201
+
202
+ /** The problematic token that caused the parse error */
203
+ readonly token: unknown;
204
+
205
+ /**
206
+ * @param message - Error message
207
+ * @param options - Error options, may include the problematic token
208
+ */
209
+ constructor(message: string, options?: ParserErrorOptions);
210
+ }
211
+
212
+ /**
213
+ * Error during code transformation/generation.
214
+ * Default code: 'TRANSFORM_ERROR'
215
+ */
216
+ export declare class TransformError extends CompileError {
217
+ readonly name: 'TransformError';
218
+
219
+ constructor(message: string, options?: PulseErrorOptions);
220
+ }
221
+
222
+ // ============================================================================
223
+ // Runtime Errors
224
+ // ============================================================================
225
+
226
+ /**
227
+ * Base class for all runtime errors.
228
+ * Default code: 'RUNTIME_ERROR'
229
+ */
230
+ export declare class RuntimeError extends PulseError {
231
+ readonly name: 'RuntimeError';
232
+
233
+ constructor(message: string, options?: PulseErrorOptions);
234
+ }
235
+
236
+ /**
237
+ * Error in the reactivity system (effects, computed values).
238
+ * Default code: 'REACTIVITY_ERROR'
239
+ */
240
+ export declare class ReactivityError extends RuntimeError {
241
+ readonly name: 'ReactivityError';
242
+
243
+ constructor(message: string, options?: PulseErrorOptions);
244
+ }
245
+
246
+ /**
247
+ * Error in DOM operations.
248
+ * Default code: 'DOM_ERROR'
249
+ */
250
+ export declare class DOMError extends RuntimeError {
251
+ readonly name: 'DOMError';
252
+
253
+ constructor(message: string, options?: PulseErrorOptions);
254
+ }
255
+
256
+ /**
257
+ * Error in store operations.
258
+ * Default code: 'STORE_ERROR'
259
+ */
260
+ export declare class StoreError extends RuntimeError {
261
+ readonly name: 'StoreError';
262
+
263
+ constructor(message: string, options?: PulseErrorOptions);
264
+ }
265
+
266
+ /**
267
+ * Error in router operations.
268
+ * Default code: 'ROUTER_ERROR'
269
+ */
270
+ export declare class RouterError extends RuntimeError {
271
+ readonly name: 'RouterError';
272
+
273
+ constructor(message: string, options?: PulseErrorOptions);
274
+ }
275
+
276
+ // ============================================================================
277
+ // Client Errors (HTTP, WebSocket, GraphQL)
278
+ // ============================================================================
279
+
280
+ /**
281
+ * Base class for client errors (HTTP, WebSocket, GraphQL).
282
+ * Provides common patterns for error creation with suggestions.
283
+ *
284
+ * Subclasses should define static properties:
285
+ * - `suggestions` - Error code to suggestion mapping
286
+ * - `errorName` - The error class name
287
+ * - `defaultCode` - Default error code when none provided
288
+ * - `markerProperty` - Property name for instance type checking
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * class HttpError extends ClientError {
293
+ * static suggestions = { TIMEOUT: 'Increase timeout...' };
294
+ * static errorName = 'HttpError';
295
+ * static defaultCode = 'HTTP_ERROR';
296
+ * static markerProperty = 'isHttpError';
297
+ * }
298
+ * ```
299
+ */
300
+ export declare class ClientError extends RuntimeError {
301
+ /** Error code to suggestion mapping */
302
+ static suggestions: Record<string, string>;
303
+
304
+ /** The error class name */
305
+ static errorName: string;
306
+
307
+ /** Default error code when none provided */
308
+ static defaultCode: string;
309
+
310
+ /** Property name for instance type checking (e.g., 'isHttpError') */
311
+ static markerProperty: string;
312
+
313
+ /**
314
+ * @param message - Error message
315
+ * @param options - Error options with code, context, and suggestion
316
+ */
317
+ constructor(message: string, options?: ClientErrorOptions);
318
+
319
+ /**
320
+ * Check if an error is an instance of this error type
321
+ * by checking for the marker property.
322
+ *
323
+ * @param error - The error to check
324
+ * @returns true if error has the marker property set to true
325
+ */
326
+ static isError(error: unknown): boolean;
327
+
328
+ /**
329
+ * Check if this is a timeout error (code === 'TIMEOUT').
330
+ */
331
+ isTimeout(): boolean;
332
+
333
+ /**
334
+ * Check if this is a network error (code === 'NETWORK' or 'NETWORK_ERROR').
335
+ */
336
+ isNetworkError(): boolean;
337
+ }
338
+
339
+ /**
340
+ * Factory to create a client error class with specific suggestions, marker
341
+ * properties, and convenience check methods.
342
+ *
343
+ * The returned class extends ClientError with:
344
+ * - Static `suggestions`, `errorName`, `defaultCode`, `markerProperty`
345
+ * - A static `is<Name>(error)` method for type checking
346
+ * - Instance `is<Code>()` methods for each entry in `codeMethods`
347
+ * - Auto-copy of `additionalProperties` from constructor options
348
+ *
349
+ * @param config - Error class configuration
350
+ * @returns A new error class extending ClientError
351
+ *
352
+ * @example
353
+ * ```typescript
354
+ * const HttpError = createClientErrorClass({
355
+ * name: 'HttpError',
356
+ * defaultCode: 'HTTP_ERROR',
357
+ * markerProperty: 'isHttpError',
358
+ * suggestions: {
359
+ * TIMEOUT: 'Consider increasing the timeout.',
360
+ * NETWORK: 'Check internet connectivity.'
361
+ * },
362
+ * codeMethods: ['TIMEOUT', 'NETWORK', 'ABORT'],
363
+ * additionalProperties: ['config', 'request', 'response', 'status']
364
+ * });
365
+ * ```
366
+ */
367
+ export declare function createClientErrorClass(config: ClientErrorClassConfig): typeof ClientError;
368
+
369
+ // ============================================================================
370
+ // CLI Errors
371
+ // ============================================================================
372
+
373
+ /**
374
+ * Base class for CLI errors.
375
+ * Default code: 'CLI_ERROR'
376
+ */
377
+ export declare class CLIError extends PulseError {
378
+ readonly name: 'CLIError';
379
+
380
+ constructor(message: string, options?: PulseErrorOptions);
381
+ }
382
+
383
+ /**
384
+ * Configuration file error.
385
+ * Default code: 'CONFIG_ERROR'
386
+ */
387
+ export declare class ConfigError extends CLIError {
388
+ readonly name: 'ConfigError';
389
+
390
+ constructor(message: string, options?: PulseErrorOptions);
391
+ }
392
+
393
+ // ============================================================================
394
+ // Documentation & URLs
395
+ // ============================================================================
396
+
397
+ /**
398
+ * Generate documentation URL for an error code.
399
+ * Maps known codes to specific documentation pages on pulse-js.fr.
400
+ *
401
+ * @param code - Error code (e.g., 'COMPUTED_SET', 'CIRCULAR_DEPENDENCY')
402
+ * @returns Full documentation URL
403
+ *
404
+ * @example
405
+ * ```typescript
406
+ * getDocsUrl('COMPUTED_SET');
407
+ * // 'https://pulse-js.fr/reactivity/computed#read-only'
408
+ *
409
+ * getDocsUrl('UNKNOWN_CODE');
410
+ * // 'https://pulse-js.fr/errors#unknown_code'
411
+ * ```
412
+ */
413
+ export declare function getDocsUrl(code: string): string;
414
+
415
+ // ============================================================================
416
+ // Helper Functions
417
+ // ============================================================================
418
+
419
+ /**
420
+ * Common error suggestions based on error patterns.
421
+ * Each key maps to a function that returns a context-specific suggestion string.
422
+ */
423
+ export declare const SUGGESTIONS: {
424
+ /** Suggestion for undefined variable in .pulse file */
425
+ 'undefined-variable': (name: string) => string;
426
+ /** Suggestion for duplicate declaration */
427
+ 'duplicate-declaration': (name: string) => string;
428
+ /** Suggestion for unexpected token */
429
+ 'unexpected-token': (expected: string, got: string) => string;
430
+ /** Suggestion for missing closing brace */
431
+ 'missing-closing-brace': () => string;
432
+ /** Suggestion for missing closing parenthesis */
433
+ 'missing-closing-paren': () => string;
434
+ /** Suggestion for invalid directive */
435
+ 'invalid-directive': (name: string) => string;
436
+ /** Suggestion for empty block */
437
+ 'empty-block': (blockName: string) => string;
438
+ /** Suggestion for attempting to set a computed value */
439
+ 'computed-set': (name?: string) => string;
440
+ /** Suggestion for circular dependency */
441
+ 'circular-dependency': () => string;
442
+ /** Suggestion for effect cleanup */
443
+ 'effect-cleanup': () => string;
444
+ /** Suggestion for mount target not found */
445
+ 'mount-not-found': (selector: string) => string;
446
+ /** Suggestion for invalid CSS selector */
447
+ 'invalid-selector': (selector: string) => string;
448
+ /** Suggestion for list without key function */
449
+ 'list-needs-key': () => string;
450
+ /** Suggestion for route not found */
451
+ 'route-not-found': (path: string) => string;
452
+ /** Suggestion for lazy load timeout */
453
+ 'lazy-timeout': (ms: number) => string;
454
+ /** Suggestion for localStorage quota exceeded */
455
+ 'persist-quota': () => string;
456
+ /** Suggestion for invalid store value type */
457
+ 'invalid-store-value': (type: string) => string;
458
+ };
459
+
460
+ /**
461
+ * Format an error with source code context.
462
+ * If the error is a PulseError, uses formatWithSnippet().
463
+ * Otherwise, attempts to create a PulseError from line/column properties.
464
+ * Falls back to error.stack or error.message.
465
+ *
466
+ * @param error - The error to format
467
+ * @param source - Source code for context
468
+ * @returns Formatted error string
469
+ */
470
+ export declare function formatError(error: Error, source?: string): string;
471
+
472
+ /**
473
+ * Create a parser error from a token object.
474
+ * Extracts line/column from the token for source location tracking.
475
+ *
476
+ * @param message - Error message
477
+ * @param token - Token object with line/column info
478
+ * @param options - Additional error options
479
+ * @returns A new ParserError with location from the token
480
+ */
481
+ export declare function createParserError(
482
+ message: string,
483
+ token: unknown,
484
+ options?: PulseErrorOptions
485
+ ): ParserError;
486
+
487
+ /**
488
+ * Create a user-friendly error message with context and suggestions.
489
+ * Produces a formatted string with [Pulse] prefix, context, details,
490
+ * suggestion arrow, and documentation URL.
491
+ *
492
+ * @param options - Error message options
493
+ * @returns Formatted error message string
494
+ *
495
+ * @example
496
+ * ```typescript
497
+ * const message = createErrorMessage({
498
+ * code: 'CUSTOM_ERROR',
499
+ * message: 'Something went wrong',
500
+ * context: 'While processing user input',
501
+ * suggestion: 'Check the input format',
502
+ * details: { input: 'invalid', expected: 'string' }
503
+ * });
504
+ * ```
505
+ */
506
+ export declare function createErrorMessage(options: ErrorMessageOptions): string;
507
+
508
+ // ============================================================================
509
+ // Pre-built Error Creators
510
+ // ============================================================================
511
+
512
+ /**
513
+ * Error creators for common scenarios with good developer experience.
514
+ * Each method returns a properly typed error instance with contextual
515
+ * messages, suggestions, and documentation links.
516
+ */
517
+ export declare const Errors: {
518
+ /**
519
+ * Cannot set computed value.
520
+ * Returns a ReactivityError with code 'COMPUTED_SET'.
521
+ *
522
+ * @param name - Optional name of the computed value
523
+ */
524
+ computedSet(name?: string): ReactivityError;
525
+
526
+ /**
527
+ * Circular dependency detected in reactive effects.
528
+ * Returns a ReactivityError with code 'CIRCULAR_DEPENDENCY'.
529
+ *
530
+ * @param effectIds - Array of the most active effect IDs
531
+ * @param pending - Array of still-pending effect IDs
532
+ */
533
+ circularDependency(effectIds: string[], pending: string[]): ReactivityError;
534
+
535
+ /**
536
+ * Mount target element not found in the DOM.
537
+ * Returns a DOMError with code 'MOUNT_ERROR'.
538
+ *
539
+ * @param selector - The CSS selector that was not found
540
+ */
541
+ mountNotFound(selector: string): DOMError;
542
+
543
+ /**
544
+ * List rendering without a key function.
545
+ * Returns a DOMError with code 'LIST_NO_KEY'.
546
+ */
547
+ listNoKey(): DOMError;
548
+
549
+ /**
550
+ * No route matched the given path.
551
+ * Returns a RouterError with code 'ROUTE_NOT_FOUND'.
552
+ *
553
+ * @param path - The path that had no matching route
554
+ */
555
+ routeNotFound(path: string): RouterError;
556
+
557
+ /**
558
+ * Lazy component load timed out.
559
+ * Returns a RouterError with code 'LAZY_TIMEOUT'.
560
+ *
561
+ * @param timeout - The timeout duration in milliseconds
562
+ */
563
+ lazyTimeout(timeout: number): RouterError;
564
+
565
+ /**
566
+ * Store persistence operation failed.
567
+ * Returns a StoreError with code 'PERSIST_ERROR'.
568
+ *
569
+ * @param operation - The operation that failed (e.g., 'save', 'load')
570
+ * @param cause - Optional underlying error
571
+ */
572
+ persistError(operation: string, cause?: Error): StoreError;
573
+
574
+ /**
575
+ * Invalid value type used in store.
576
+ * Returns a StoreError with code 'STORE_TYPE_ERROR'.
577
+ *
578
+ * @param type - The invalid type name (e.g., 'Function', 'Symbol')
579
+ */
580
+ invalidStoreValue(type: string): StoreError;
581
+
582
+ /**
583
+ * Native API not available in current environment.
584
+ * Returns a RuntimeError with code 'NATIVE_ERROR'.
585
+ *
586
+ * @param api - The native API name that is unavailable
587
+ */
588
+ nativeNotAvailable(api: string): RuntimeError;
589
+ };
590
+
591
+ // ============================================================================
592
+ // Default Export
593
+ // ============================================================================
594
+
595
+ declare const _default: {
596
+ PulseError: typeof PulseError;
597
+ CompileError: typeof CompileError;
598
+ LexerError: typeof LexerError;
599
+ ParserError: typeof ParserError;
600
+ TransformError: typeof TransformError;
601
+ RuntimeError: typeof RuntimeError;
602
+ ReactivityError: typeof ReactivityError;
603
+ DOMError: typeof DOMError;
604
+ StoreError: typeof StoreError;
605
+ RouterError: typeof RouterError;
606
+ ClientError: typeof ClientError;
607
+ createClientErrorClass: typeof createClientErrorClass;
608
+ CLIError: typeof CLIError;
609
+ ConfigError: typeof ConfigError;
610
+ SUGGESTIONS: typeof SUGGESTIONS;
611
+ Errors: typeof Errors;
612
+ formatError: typeof formatError;
613
+ createParserError: typeof createParserError;
614
+ createErrorMessage: typeof createErrorMessage;
615
+ getDocsUrl: typeof getDocsUrl;
616
+ };
617
+
618
+ export default _default;