@rcrsr/rill 0.7.2 → 0.8.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.
Files changed (107) hide show
  1. package/README.md +29 -1
  2. package/dist/ast-nodes.d.ts +635 -0
  3. package/dist/ast-nodes.d.ts.map +1 -0
  4. package/dist/ast-nodes.js +2 -0
  5. package/dist/ast-nodes.js.map +1 -0
  6. package/dist/ast-unions.d.ts +6 -0
  7. package/dist/ast-unions.d.ts.map +1 -0
  8. package/dist/ast-unions.js +6 -0
  9. package/dist/ast-unions.js.map +1 -0
  10. package/dist/error-classes.d.ts +90 -0
  11. package/dist/error-classes.d.ts.map +1 -0
  12. package/dist/error-classes.js +185 -0
  13. package/dist/error-classes.js.map +1 -0
  14. package/dist/error-registry.d.ts +93 -0
  15. package/dist/error-registry.d.ts.map +1 -0
  16. package/dist/error-registry.js +876 -0
  17. package/dist/error-registry.js.map +1 -0
  18. package/dist/ext/crypto/index.d.ts +32 -0
  19. package/dist/ext/crypto/index.d.ts.map +1 -0
  20. package/dist/ext/crypto/index.js +143 -0
  21. package/dist/ext/crypto/index.js.map +1 -0
  22. package/dist/ext/exec/index.d.ts +45 -0
  23. package/dist/ext/exec/index.d.ts.map +1 -0
  24. package/dist/ext/exec/index.js +168 -0
  25. package/dist/ext/exec/index.js.map +1 -0
  26. package/dist/ext/exec/runner.d.ts +62 -0
  27. package/dist/ext/exec/runner.d.ts.map +1 -0
  28. package/dist/ext/exec/runner.js +168 -0
  29. package/dist/ext/exec/runner.js.map +1 -0
  30. package/dist/ext/fetch/index.d.ts +68 -0
  31. package/dist/ext/fetch/index.d.ts.map +1 -0
  32. package/dist/ext/fetch/index.js +259 -0
  33. package/dist/ext/fetch/index.js.map +1 -0
  34. package/dist/ext/fetch/request.d.ts +90 -0
  35. package/dist/ext/fetch/request.d.ts.map +1 -0
  36. package/dist/ext/fetch/request.js +413 -0
  37. package/dist/ext/fetch/request.js.map +1 -0
  38. package/dist/ext/fs/index.d.ts +39 -0
  39. package/dist/ext/fs/index.d.ts.map +1 -0
  40. package/dist/ext/fs/index.js +560 -0
  41. package/dist/ext/fs/index.js.map +1 -0
  42. package/dist/ext/fs/sandbox.d.ts +78 -0
  43. package/dist/ext/fs/sandbox.d.ts.map +1 -0
  44. package/dist/ext/fs/sandbox.js +208 -0
  45. package/dist/ext/fs/sandbox.js.map +1 -0
  46. package/dist/ext/kv/index.d.ts +46 -0
  47. package/dist/ext/kv/index.d.ts.map +1 -0
  48. package/dist/ext/kv/index.js +215 -0
  49. package/dist/ext/kv/index.js.map +1 -0
  50. package/dist/ext/kv/store.d.ts +46 -0
  51. package/dist/ext/kv/store.d.ts.map +1 -0
  52. package/dist/ext/kv/store.js +256 -0
  53. package/dist/ext/kv/store.js.map +1 -0
  54. package/dist/generated/introspection-data.d.ts +1 -1
  55. package/dist/generated/introspection-data.d.ts.map +1 -1
  56. package/dist/generated/introspection-data.js +509 -481
  57. package/dist/generated/introspection-data.js.map +1 -1
  58. package/dist/generated/version-data.d.ts +1 -1
  59. package/dist/generated/version-data.js +3 -3
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/index.js.map +1 -1
  64. package/dist/runtime/core/callable.d.ts +5 -5
  65. package/dist/runtime/core/callable.d.ts.map +1 -1
  66. package/dist/runtime/core/callable.js +2 -1
  67. package/dist/runtime/core/callable.js.map +1 -1
  68. package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -1
  69. package/dist/runtime/core/eval/mixins/collections.js +5 -1
  70. package/dist/runtime/core/eval/mixins/collections.js.map +1 -1
  71. package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -1
  72. package/dist/runtime/core/eval/mixins/literals.js +5 -1
  73. package/dist/runtime/core/eval/mixins/literals.js.map +1 -1
  74. package/dist/runtime/core/eval/mixins/variables.js +12 -12
  75. package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
  76. package/dist/runtime/core/values.d.ts +31 -3
  77. package/dist/runtime/core/values.d.ts.map +1 -1
  78. package/dist/runtime/core/values.js +47 -1
  79. package/dist/runtime/core/values.js.map +1 -1
  80. package/dist/runtime/ext/builtins.d.ts.map +1 -1
  81. package/dist/runtime/ext/builtins.js +202 -1
  82. package/dist/runtime/ext/builtins.js.map +1 -1
  83. package/dist/runtime/ext/extensions.d.ts +39 -3
  84. package/dist/runtime/ext/extensions.d.ts.map +1 -1
  85. package/dist/runtime/ext/extensions.js +77 -12
  86. package/dist/runtime/ext/extensions.js.map +1 -1
  87. package/dist/runtime/index.d.ts +5 -5
  88. package/dist/runtime/index.d.ts.map +1 -1
  89. package/dist/runtime/index.js +2 -2
  90. package/dist/runtime/index.js.map +1 -1
  91. package/dist/source-location.d.ts +10 -0
  92. package/dist/source-location.d.ts.map +1 -0
  93. package/dist/source-location.js +5 -0
  94. package/dist/source-location.js.map +1 -0
  95. package/dist/token-types.d.ts +68 -0
  96. package/dist/token-types.d.ts.map +1 -0
  97. package/dist/token-types.js +79 -0
  98. package/dist/token-types.js.map +1 -0
  99. package/dist/types.d.ts +9 -882
  100. package/dist/types.d.ts.map +1 -1
  101. package/dist/types.js +8 -958
  102. package/dist/types.js.map +1 -1
  103. package/dist/value-types.d.ts +3 -0
  104. package/dist/value-types.d.ts.map +1 -0
  105. package/dist/value-types.js +2 -0
  106. package/dist/value-types.js.map +1 -0
  107. package/package.json +50 -11
@@ -0,0 +1,876 @@
1
+ /**
2
+ * Error Registry
3
+ * Central error definition registry with template rendering and help URL generation.
4
+ */
5
+ class ErrorRegistryImpl {
6
+ byId;
7
+ constructor(definitions) {
8
+ const idMap = new Map();
9
+ for (const def of definitions) {
10
+ idMap.set(def.errorId, def);
11
+ }
12
+ this.byId = idMap;
13
+ }
14
+ get(errorId) {
15
+ return this.byId.get(errorId);
16
+ }
17
+ has(errorId) {
18
+ return this.byId.has(errorId);
19
+ }
20
+ get size() {
21
+ return this.byId.size;
22
+ }
23
+ entries() {
24
+ return this.byId.entries();
25
+ }
26
+ }
27
+ /** All error definitions indexed by error ID */
28
+ const ERROR_DEFINITIONS = [
29
+ // Lexer Errors (RILL-L0xx)
30
+ {
31
+ errorId: 'RILL-L001',
32
+ category: 'lexer',
33
+ description: 'Unterminated string literal',
34
+ messageTemplate: 'Unterminated string literal at {location}',
35
+ cause: 'String opened with quote but never closed before end of line or file.',
36
+ resolution: 'Add closing quote to complete the string, or use multiline strings with triple quotes (""") for multi-line content.',
37
+ examples: [
38
+ {
39
+ description: 'Missing closing quote on single line',
40
+ code: '"hello',
41
+ },
42
+ {
43
+ description: 'Newline inside single-quoted string',
44
+ code: '"hello\nworld"',
45
+ },
46
+ ],
47
+ },
48
+ {
49
+ errorId: 'RILL-L002',
50
+ category: 'lexer',
51
+ description: 'Invalid character',
52
+ messageTemplate: 'Invalid character {char} at {location}',
53
+ cause: 'Character not recognized by the lexer (not part of Rill syntax).',
54
+ resolution: 'Remove or replace the invalid character. Common causes: unicode characters in identifiers, unsupported operators, or copy-paste artifacts.',
55
+ examples: [
56
+ {
57
+ description: 'Unicode character in code',
58
+ code: '$x → "value" # → is not valid, use ->',
59
+ },
60
+ {
61
+ description: 'Backtick instead of quote',
62
+ code: '`hello` # Use "hello" instead',
63
+ },
64
+ ],
65
+ },
66
+ {
67
+ errorId: 'RILL-L003',
68
+ category: 'lexer',
69
+ description: 'Invalid number format',
70
+ messageTemplate: 'Invalid number format: {value}',
71
+ cause: 'Number contains invalid characters, multiple decimal points, or unsupported notation.',
72
+ resolution: 'Use valid number format: integers (123), decimals (1.5), or scientific notation (1e5). No underscores, trailing dots, or multiple decimals allowed.',
73
+ examples: [
74
+ {
75
+ description: 'Multiple decimal points',
76
+ code: '1.2.3',
77
+ },
78
+ {
79
+ description: 'Trailing decimal point',
80
+ code: '123.',
81
+ },
82
+ {
83
+ description: 'Leading zeros (octal notation not supported)',
84
+ code: '0123',
85
+ },
86
+ ],
87
+ },
88
+ {
89
+ errorId: 'RILL-L004',
90
+ category: 'lexer',
91
+ description: 'Unterminated multiline string',
92
+ messageTemplate: 'Unterminated multiline string starting at {location}',
93
+ cause: 'Multiline string opened with triple quotes (""") but never closed.',
94
+ resolution: 'Add closing triple quotes (""") to complete the multiline string.',
95
+ examples: [
96
+ {
97
+ description: 'Missing closing triple quotes',
98
+ code: '"""hello\nworld',
99
+ },
100
+ {
101
+ description: 'Only two closing quotes instead of three',
102
+ code: '"""content""',
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ errorId: 'RILL-L005',
108
+ category: 'lexer',
109
+ description: 'Invalid escape sequence',
110
+ messageTemplate: 'Invalid escape sequence {sequence} at {location}',
111
+ cause: 'Backslash followed by unsupported character in string literal.',
112
+ resolution: 'Use valid escape sequences: \\n (newline), \\t (tab), \\\\ (backslash), \\" (quote), \\{ (brace). For literal backslash, use \\\\.',
113
+ examples: [
114
+ {
115
+ description: 'Invalid escape character',
116
+ code: '"hello\\xworld" # \\x not supported',
117
+ },
118
+ {
119
+ description: 'Incomplete escape at end',
120
+ code: '"path\\',
121
+ },
122
+ ],
123
+ },
124
+ // Parse Errors (RILL-P0xx)
125
+ {
126
+ errorId: 'RILL-P001',
127
+ category: 'parse',
128
+ description: 'Unexpected token',
129
+ messageTemplate: 'Unexpected token {token}, expected {expected}',
130
+ cause: 'Token appears in invalid position according to grammar rules.',
131
+ resolution: 'Check syntax at the indicated position. Common causes: missing operators, mismatched delimiters, or keywords in wrong context.',
132
+ examples: [
133
+ {
134
+ description: 'Missing pipe operator between expressions',
135
+ code: '"hello" "world" # Missing -> between',
136
+ },
137
+ {
138
+ description: 'Statement starting with operator',
139
+ code: '-> "value" # Missing left side',
140
+ },
141
+ {
142
+ description: 'Unexpected closing brace',
143
+ code: '{ "value" }} # Extra closing brace',
144
+ },
145
+ ],
146
+ },
147
+ {
148
+ errorId: 'RILL-P002',
149
+ category: 'parse',
150
+ description: 'Unexpected end of input',
151
+ messageTemplate: 'Unexpected end of input, expected {expected}',
152
+ cause: 'File or block ended while parser expected more tokens (incomplete expression or statement).',
153
+ resolution: 'Complete the incomplete construct. Common causes: unclosed blocks, incomplete pipe chains, or missing expression after operator.',
154
+ examples: [
155
+ {
156
+ description: 'Unclosed block',
157
+ code: '{ "value"',
158
+ },
159
+ {
160
+ description: 'Pipe with no target',
161
+ code: '"hello" ->',
162
+ },
163
+ {
164
+ description: 'Incomplete conditional',
165
+ code: '?($x > 0) "yes" # Missing else branch',
166
+ },
167
+ ],
168
+ },
169
+ {
170
+ errorId: 'RILL-P003',
171
+ category: 'parse',
172
+ description: 'Invalid type annotation',
173
+ messageTemplate: 'Invalid type annotation: {type}',
174
+ cause: 'Type name not recognized. Rill supports: string, number, bool, closure, list, dict, tuple.',
175
+ resolution: 'Use valid type name from supported set. Check spelling and casing (types are lowercase).',
176
+ examples: [
177
+ {
178
+ description: 'Uppercase type name',
179
+ code: '$x => String # Use "string" not "String"',
180
+ },
181
+ {
182
+ description: 'Invalid type name',
183
+ code: '$x => int # Use "number" for all numeric types',
184
+ },
185
+ {
186
+ description: 'Generic type syntax not supported',
187
+ code: '$x => list<string> # Use "list" only',
188
+ },
189
+ ],
190
+ },
191
+ {
192
+ errorId: 'RILL-P004',
193
+ category: 'parse',
194
+ description: 'Invalid expression',
195
+ messageTemplate: 'Invalid expression: {details}',
196
+ cause: 'Expression structure violates grammar rules or contains unsupported constructs.',
197
+ resolution: 'Check expression syntax. Common causes: invalid operator combinations, malformed literals, or unsupported language features.',
198
+ examples: [
199
+ {
200
+ description: 'Double operators',
201
+ code: '$x + + $y',
202
+ },
203
+ {
204
+ description: 'Assignment operator (not supported)',
205
+ code: '$x = 5 # Use "5 => $x" instead',
206
+ },
207
+ ],
208
+ },
209
+ {
210
+ errorId: 'RILL-P005',
211
+ category: 'parse',
212
+ description: 'Missing delimiter',
213
+ messageTemplate: 'Missing {delimiter}, found {found}',
214
+ cause: 'Expected closing delimiter (parenthesis, bracket, brace) not found.',
215
+ resolution: 'Add the missing delimiter. Check for proper nesting and matching pairs.',
216
+ examples: [
217
+ {
218
+ description: 'Missing closing parenthesis',
219
+ code: 'func($a, $b',
220
+ },
221
+ {
222
+ description: 'Missing closing bracket in tuple',
223
+ code: '[1, 2, 3',
224
+ },
225
+ {
226
+ description: 'Mismatched delimiters',
227
+ code: '{ "value"] # Opened with { but closed with ]',
228
+ },
229
+ ],
230
+ },
231
+ {
232
+ errorId: 'RILL-P006',
233
+ category: 'parse',
234
+ description: 'Deprecated capture arrow syntax',
235
+ messageTemplate: 'The capture arrow syntax changed from :> to =>',
236
+ cause: 'Code uses old capture arrow syntax (:>) instead of current syntax (=>).',
237
+ resolution: 'Replace :> with => for all variable captures. This change was made in version 0.4.0.',
238
+ examples: [
239
+ {
240
+ description: 'Old capture syntax',
241
+ code: '"value" :> $x # Change to "value" => $x',
242
+ },
243
+ {
244
+ description: 'Old typed capture',
245
+ code: '5 :> $x:number # Change to 5 => $x:number',
246
+ },
247
+ ],
248
+ },
249
+ // Runtime Errors (RILL-R0xx)
250
+ {
251
+ errorId: 'RILL-R001',
252
+ category: 'runtime',
253
+ description: 'Parameter type mismatch',
254
+ messageTemplate: 'Function {function} expects parameter {param} (position {position}) to be {expected}, got {actual}',
255
+ cause: 'Argument passed to function does not match declared parameter type.',
256
+ resolution: 'Pass value of correct type, or convert the value before passing. Check function signature for expected types.',
257
+ examples: [
258
+ {
259
+ description: 'String passed to number parameter',
260
+ code: '|x: number| $x * 2\n"5" -> $()',
261
+ },
262
+ {
263
+ description: 'Number passed to string method',
264
+ code: '123 -> .split(",") # split expects string',
265
+ },
266
+ ],
267
+ },
268
+ {
269
+ errorId: 'RILL-R002',
270
+ category: 'runtime',
271
+ description: 'Operator type mismatch',
272
+ messageTemplate: 'Operator {operator} cannot be applied to {leftType} and {rightType}',
273
+ cause: 'Binary operator applied to incompatible types. Rill does not perform implicit type coercion.',
274
+ resolution: 'Ensure both operands are compatible types. Convert values explicitly if needed using type-specific methods.',
275
+ examples: [
276
+ {
277
+ description: 'Adding string and number',
278
+ code: '"5" + 1 # Error: no implicit coercion',
279
+ },
280
+ {
281
+ description: 'Comparing different types',
282
+ code: '"10" == 10 # Always false, no coercion',
283
+ },
284
+ {
285
+ description: 'Arithmetic on non-numbers',
286
+ code: '"hello" * 2',
287
+ },
288
+ ],
289
+ },
290
+ {
291
+ errorId: 'RILL-R003',
292
+ category: 'runtime',
293
+ description: 'Method receiver type mismatch',
294
+ messageTemplate: 'Method {method} cannot be called on {type}',
295
+ cause: 'Method called on value of wrong type. String methods require strings, list methods require lists, etc.',
296
+ resolution: 'Call method on correct type, or convert value before calling. Check method documentation for receiver type.',
297
+ examples: [
298
+ {
299
+ description: 'String method on number',
300
+ code: '123 -> .upper() # upper() is string method',
301
+ },
302
+ {
303
+ description: 'List method on string',
304
+ code: '"hello" -> .first() # first() is list method',
305
+ },
306
+ ],
307
+ },
308
+ {
309
+ errorId: 'RILL-R004',
310
+ category: 'runtime',
311
+ description: 'Type conversion failure',
312
+ messageTemplate: 'Cannot convert {value} to {targetType}',
313
+ cause: 'Value cannot be converted to target type (invalid format or incompatible types).',
314
+ resolution: 'Ensure value has valid format for target type. For string-to-number: check numeric format. For parse operations: validate input structure.',
315
+ examples: [
316
+ {
317
+ description: 'Invalid number string',
318
+ code: '"abc" -> .num() # Not a valid number',
319
+ },
320
+ {
321
+ description: 'Cannot serialize closure',
322
+ code: 'fn() => "test" end -> json()',
323
+ },
324
+ ],
325
+ },
326
+ {
327
+ errorId: 'RILL-R005',
328
+ category: 'runtime',
329
+ description: 'Undefined variable',
330
+ messageTemplate: 'Variable {name} is not defined',
331
+ cause: 'Variable referenced before assignment, or variable name misspelled.',
332
+ resolution: 'Assign value to variable before use (value => $var), or check spelling. Variables must be captured before reference.',
333
+ examples: [
334
+ {
335
+ description: 'Variable used before assignment',
336
+ code: '$count + 1 # $count never assigned',
337
+ },
338
+ {
339
+ description: 'Typo in variable name',
340
+ code: '"hi" => $mesage\n$message # Typo: mesage vs message',
341
+ },
342
+ {
343
+ description: 'Variable out of scope',
344
+ code: '{ "local" => $x }\n$x # $x only exists inside block',
345
+ },
346
+ ],
347
+ },
348
+ {
349
+ errorId: 'RILL-R006',
350
+ category: 'runtime',
351
+ description: 'Undefined function',
352
+ messageTemplate: 'Function {name} is not defined',
353
+ cause: 'Function name not found in runtime context (not a built-in or host-provided function).',
354
+ resolution: 'Check function name spelling, ensure function is provided by host application, or verify module imports.',
355
+ examples: [
356
+ {
357
+ description: 'Misspelled function name',
358
+ code: 'leng("hello") # Should be length()',
359
+ },
360
+ {
361
+ description: 'Missing host function',
362
+ code: 'app::fetch($url) # Host must provide app::fetch',
363
+ },
364
+ ],
365
+ },
366
+ {
367
+ errorId: 'RILL-R007',
368
+ category: 'runtime',
369
+ description: 'Undefined method',
370
+ messageTemplate: 'Method {method} is not defined on {type}',
371
+ cause: 'Method name not supported for the given type, or method name misspelled.',
372
+ resolution: 'Check method documentation for the type. Verify method name spelling and that it exists for this type.',
373
+ examples: [
374
+ {
375
+ description: 'Method not available on type',
376
+ code: '123 -> .trim() # trim() only on strings',
377
+ },
378
+ {
379
+ description: 'Misspelled method name',
380
+ code: '"hello" -> .upcase() # Should be .upper()',
381
+ },
382
+ ],
383
+ },
384
+ {
385
+ errorId: 'RILL-R008',
386
+ category: 'runtime',
387
+ description: 'Undefined annotation',
388
+ messageTemplate: 'Annotation {key} is not defined',
389
+ cause: 'Annotation key accessed but not set on statement or parameter.',
390
+ resolution: 'Set annotation before accessing (^(key: value)), or check annotation key spelling.',
391
+ examples: [
392
+ {
393
+ description: 'Accessing undefined annotation',
394
+ code: '$stmt.^timeout # No ^(timeout: ...) set',
395
+ },
396
+ ],
397
+ },
398
+ {
399
+ errorId: 'RILL-R009',
400
+ category: 'runtime',
401
+ description: 'Property not found',
402
+ messageTemplate: 'Property {property} not found on {type}',
403
+ cause: 'Dict key or tuple index does not exist in the value.',
404
+ resolution: 'Check property name spelling, verify the property exists, or use null-coalescing (??) to provide default. For safe access, use .? operator.',
405
+ examples: [
406
+ {
407
+ description: 'Missing dict key',
408
+ code: '[name: "x"] -> .age # age key not in dict',
409
+ },
410
+ {
411
+ description: 'Index out of bounds',
412
+ code: '[1, 2, 3] -> [5] # Only 3 elements (0-2)',
413
+ },
414
+ {
415
+ description: 'Safe alternative',
416
+ code: '[name: "x"] -> .age ?? 0 # Returns 0 if missing',
417
+ },
418
+ ],
419
+ },
420
+ {
421
+ errorId: 'RILL-R010',
422
+ category: 'runtime',
423
+ description: 'Iteration limit exceeded',
424
+ messageTemplate: 'Iteration limit of {limit} exceeded',
425
+ cause: 'Loop or collection operation exceeded configured iteration limit (prevents infinite loops).',
426
+ resolution: 'Reduce data size, adjust iteration limit via RuntimeOptions, or check for infinite loop conditions.',
427
+ examples: [
428
+ {
429
+ description: 'Infinite loop without termination',
430
+ code: '(true) @ { "looping" } # Never terminates',
431
+ },
432
+ {
433
+ description: 'Large collection with default limit',
434
+ code: 'range(0, 1000000) -> each |x| $x # May exceed default limit',
435
+ },
436
+ ],
437
+ },
438
+ {
439
+ errorId: 'RILL-R011',
440
+ category: 'runtime',
441
+ description: 'Invalid regex pattern',
442
+ messageTemplate: 'Invalid regex pattern: {pattern}',
443
+ cause: 'Regular expression pattern has invalid syntax or unsupported features.',
444
+ resolution: 'Fix regex syntax errors. Check for unescaped special characters, unclosed groups, or invalid quantifiers.',
445
+ examples: [
446
+ {
447
+ description: 'Unclosed group',
448
+ code: '"test" -> .match("(abc") # Missing closing )',
449
+ },
450
+ {
451
+ description: 'Invalid quantifier',
452
+ code: '"test" -> .match("a{,5}") # Empty min in range',
453
+ },
454
+ ],
455
+ },
456
+ {
457
+ errorId: 'RILL-R012',
458
+ category: 'runtime',
459
+ description: 'Operation timeout',
460
+ messageTemplate: 'Operation timed out after {timeout}ms',
461
+ cause: 'Function execution exceeded configured timeout duration.',
462
+ resolution: 'Increase timeout via RuntimeOptions, optimize slow operations, or add ^(timeout: ms) annotation to specific calls.',
463
+ examples: [
464
+ {
465
+ description: 'Slow host function',
466
+ code: 'app::slow_api() # Times out if exceeds limit',
467
+ },
468
+ {
469
+ description: 'Setting higher timeout',
470
+ code: '^(timeout: 30000) app::slow_api() # 30 seconds',
471
+ },
472
+ ],
473
+ },
474
+ {
475
+ errorId: 'RILL-R013',
476
+ category: 'runtime',
477
+ description: 'Execution aborted',
478
+ messageTemplate: 'Execution aborted by signal',
479
+ cause: 'Host application cancelled execution via AbortSignal.',
480
+ resolution: 'This is intentional cancellation, not an error. If unexpected, check host abort signal logic.',
481
+ examples: [
482
+ {
483
+ description: 'User cancellation in UI',
484
+ code: '# Long-running script cancelled by user',
485
+ },
486
+ ],
487
+ },
488
+ {
489
+ errorId: 'RILL-R014',
490
+ category: 'runtime',
491
+ description: 'Auto-exception triggered',
492
+ messageTemplate: 'Auto-exception triggered: pattern {pattern} matched',
493
+ cause: 'Value matched auto-exception pattern (configured to halt on specific error patterns in output).',
494
+ resolution: 'Handle error condition that produced the matched pattern, or adjust auto-exception configuration.',
495
+ examples: [
496
+ {
497
+ description: 'API error response',
498
+ code: '# API returned "ERROR:" prefix, auto-exception configured to catch this',
499
+ },
500
+ ],
501
+ },
502
+ {
503
+ errorId: 'RILL-R015',
504
+ category: 'runtime',
505
+ description: 'Assertion failed',
506
+ messageTemplate: 'Assertion failed: {condition}',
507
+ cause: 'Assertion statement evaluated to false.',
508
+ resolution: 'Fix the condition causing assertion failure, or remove/adjust assertion if condition is incorrect.',
509
+ examples: [
510
+ {
511
+ description: 'Basic assertion',
512
+ code: 'assert $count > 0 # Fails if $count <= 0',
513
+ },
514
+ {
515
+ description: 'Assertion with message',
516
+ code: 'assert $age >= 18 "Must be adult"',
517
+ },
518
+ ],
519
+ },
520
+ {
521
+ errorId: 'RILL-R016',
522
+ category: 'runtime',
523
+ description: 'Error statement executed',
524
+ messageTemplate: 'Error raised: {message}',
525
+ cause: 'Error statement executed explicitly in code.',
526
+ resolution: 'This is intentional error raising. Fix the condition that triggers the error statement, or handle the error case differently.',
527
+ examples: [
528
+ {
529
+ description: 'Explicit error',
530
+ code: 'error "Invalid configuration"',
531
+ },
532
+ {
533
+ description: 'Conditional error',
534
+ code: '($status == "failed") ? { error "Process failed" } ! "ok"',
535
+ },
536
+ ],
537
+ },
538
+ {
539
+ errorId: 'RILL-R017',
540
+ category: 'runtime',
541
+ description: 'fs extension: unknown mount',
542
+ messageTemplate: 'mount "{mountName}" not configured',
543
+ cause: 'Script references mount name that does not exist in fs extension configuration, or mount path is invalid.',
544
+ resolution: 'Verify mount name is correct, ensure mount is configured in createFsExtension() call, and check mount path exists.',
545
+ examples: [
546
+ {
547
+ description: 'Unknown mount',
548
+ code: 'fs::read("unknown", "file.txt") # Mount "unknown" not in config',
549
+ },
550
+ {
551
+ description: 'Invalid mount path',
552
+ code: '# createFsExtension({ mounts: { data: { path: "/nonexistent", mode: "read" } } })',
553
+ },
554
+ ],
555
+ },
556
+ {
557
+ errorId: 'RILL-R018',
558
+ category: 'runtime',
559
+ description: 'fs extension: path escapes mount boundary',
560
+ messageTemplate: 'path escapes mount boundary',
561
+ cause: 'Path traversal attempt (using .. or symlinks) escapes configured mount boundary.',
562
+ resolution: 'Remove path traversal attempts, use paths relative to mount root, or reconfigure mount boundaries.',
563
+ examples: [
564
+ {
565
+ description: 'Path traversal with ..',
566
+ code: 'fs::read("data", "../../etc/passwd") # Attempts escape',
567
+ },
568
+ {
569
+ description: 'Symlink escape',
570
+ code: 'fs::read("data", "symlink_to_root") # Symlink points outside mount',
571
+ },
572
+ ],
573
+ },
574
+ {
575
+ errorId: 'RILL-R019',
576
+ category: 'runtime',
577
+ description: 'fs extension: file type not permitted in mount',
578
+ messageTemplate: 'file type not permitted in mount "{mountName}"',
579
+ cause: 'Filename does not match mount glob pattern (e.g., trying to read .exe when only *.csv allowed).',
580
+ resolution: 'Use file with allowed extension, or reconfigure mount glob pattern to permit file type.',
581
+ examples: [
582
+ {
583
+ description: 'Glob mismatch',
584
+ code: 'fs::read("csv_only", "data.json") # Mount configured with glob: "*.csv"',
585
+ },
586
+ {
587
+ description: 'Multiple extensions',
588
+ code: 'fs::read("configs", "app.ini") # Mount glob: "*.{json,yaml}"',
589
+ },
590
+ ],
591
+ },
592
+ {
593
+ errorId: 'RILL-R020',
594
+ category: 'runtime',
595
+ description: 'fs extension: mount does not permit operation',
596
+ messageTemplate: 'mount "{mountName}" does not permit {operation}',
597
+ cause: 'Operation (read or write) not permitted by mount mode (e.g., write to read-only mount).',
598
+ resolution: 'Use mount with appropriate mode, or reconfigure mount to allow operation.',
599
+ examples: [
600
+ {
601
+ description: 'Write to read-only mount',
602
+ code: 'fs::write("readonly", "file.txt", "data") # Mount mode: "read"',
603
+ },
604
+ {
605
+ description: 'Read from write-only mount',
606
+ code: 'fs::read("writeonly", "file.txt") # Mount mode: "write"',
607
+ },
608
+ ],
609
+ },
610
+ {
611
+ errorId: 'RILL-R021',
612
+ category: 'runtime',
613
+ description: 'fs extension: permission denied or file not found',
614
+ messageTemplate: 'permission denied: {path}',
615
+ cause: 'Operating system denied access to file (EACCES/EPERM), or file does not exist (ENOENT).',
616
+ resolution: 'Check file permissions, verify file exists, ensure user has appropriate access rights.',
617
+ examples: [
618
+ {
619
+ description: 'Permission denied',
620
+ code: 'fs::read("data", "protected.txt") # File exists but no read permission',
621
+ },
622
+ {
623
+ description: 'File not found',
624
+ code: 'fs::read("data", "missing.txt") # File does not exist',
625
+ },
626
+ ],
627
+ },
628
+ {
629
+ errorId: 'RILL-R022',
630
+ category: 'runtime',
631
+ description: 'fetch extension: HTTP 4xx client error',
632
+ messageTemplate: '{namespace}: HTTP {status} — {body}',
633
+ cause: 'HTTP request returned a 4xx client error status code.',
634
+ resolution: 'Check request parameters, verify authentication, or adjust request payload.',
635
+ examples: [
636
+ {
637
+ description: 'HTTP 404 Not Found',
638
+ code: 'fetch::get("api", "/nonexistent") # Returns 404',
639
+ },
640
+ {
641
+ description: 'HTTP 400 Bad Request',
642
+ code: 'fetch::post("api", "/users", [invalid: "data"]) # Returns 400',
643
+ },
644
+ ],
645
+ },
646
+ {
647
+ errorId: 'RILL-R023',
648
+ category: 'runtime',
649
+ description: 'fetch extension: HTTP 5xx after retries',
650
+ messageTemplate: '{namespace}: HTTP {status} after {retries} retries',
651
+ cause: 'HTTP request returned a 5xx server error after all retry attempts.',
652
+ resolution: 'Check server status, reduce request frequency, or increase retry limit.',
653
+ examples: [
654
+ {
655
+ description: 'HTTP 503 Service Unavailable',
656
+ code: 'fetch::get("api", "/resource") # Server returns 503',
657
+ },
658
+ ],
659
+ },
660
+ {
661
+ errorId: 'RILL-R024',
662
+ category: 'runtime',
663
+ description: 'fetch extension: request timeout',
664
+ messageTemplate: '{namespace}: request timeout ({timeoutMs}ms)',
665
+ cause: 'HTTP request exceeded configured timeout duration.',
666
+ resolution: 'Increase timeout via extension configuration, or optimize server response time.',
667
+ examples: [
668
+ {
669
+ description: 'Slow API endpoint',
670
+ code: 'fetch::get("api", "/slow") # Times out if exceeds limit',
671
+ },
672
+ ],
673
+ },
674
+ {
675
+ errorId: 'RILL-R025',
676
+ category: 'runtime',
677
+ description: 'fetch extension: network error',
678
+ messageTemplate: '{namespace}: network error — {message}',
679
+ cause: 'Network request failed (DNS resolution, connection refused, or other network issue).',
680
+ resolution: 'Check network connectivity, verify server is reachable, or check firewall settings.',
681
+ examples: [
682
+ {
683
+ description: 'Connection refused',
684
+ code: 'fetch::get("api", "/endpoint") # Server not running',
685
+ },
686
+ ],
687
+ },
688
+ {
689
+ errorId: 'RILL-R026',
690
+ category: 'runtime',
691
+ description: 'fetch extension: invalid JSON response',
692
+ messageTemplate: '{namespace}: invalid JSON response',
693
+ cause: 'Response body could not be parsed as JSON.',
694
+ resolution: 'Check response Content-Type header, verify server returns valid JSON, or use raw response parsing.',
695
+ examples: [
696
+ {
697
+ description: 'HTML error page returned as JSON',
698
+ code: 'fetch::get("api", "/endpoint") # Server returns HTML instead of JSON',
699
+ },
700
+ ],
701
+ },
702
+ // Check Errors (RILL-C0xx)
703
+ {
704
+ errorId: 'RILL-C001',
705
+ category: 'check',
706
+ description: 'File not found',
707
+ messageTemplate: 'File not found: {path}',
708
+ cause: 'Specified file path does not exist in filesystem.',
709
+ resolution: 'Verify file path is correct, check file exists, or create the file if it should exist.',
710
+ examples: [
711
+ {
712
+ description: 'Nonexistent file',
713
+ code: 'rill-check missing.rill',
714
+ },
715
+ {
716
+ description: 'Wrong file extension',
717
+ code: 'rill-check script.txt # Should be script.rill',
718
+ },
719
+ ],
720
+ },
721
+ {
722
+ errorId: 'RILL-C002',
723
+ category: 'check',
724
+ description: 'File unreadable',
725
+ messageTemplate: 'File unreadable: {path}',
726
+ cause: 'File exists but cannot be read (permission denied or IO error).',
727
+ resolution: 'Check file permissions, ensure read access, or verify file is not locked by another process.',
728
+ examples: [
729
+ {
730
+ description: 'Permission denied',
731
+ code: 'rill-check protected.rill # File exists but no read permission',
732
+ },
733
+ ],
734
+ },
735
+ {
736
+ errorId: 'RILL-C003',
737
+ category: 'check',
738
+ description: 'Invalid configuration',
739
+ messageTemplate: 'Invalid configuration: {details}',
740
+ cause: 'Configuration file or options contain invalid values or structure.',
741
+ resolution: 'Fix configuration syntax, ensure all required fields are present, and values are of correct type.',
742
+ examples: [
743
+ {
744
+ description: 'Invalid JSON in config',
745
+ code: '# .rillrc.json contains malformed JSON',
746
+ },
747
+ {
748
+ description: 'Unknown config option',
749
+ code: '# Config contains unsupported option key',
750
+ },
751
+ ],
752
+ },
753
+ {
754
+ errorId: 'RILL-C004',
755
+ category: 'check',
756
+ description: 'Fix collision detected',
757
+ messageTemplate: 'Fix collision detected for {location}',
758
+ cause: 'Multiple auto-fix rules attempt to modify the same source location.',
759
+ resolution: 'Apply fixes one at a time, or disable conflicting lint rules. Some fixes may need manual resolution.',
760
+ examples: [
761
+ {
762
+ description: 'Overlapping fix ranges',
763
+ code: '# Two rules try to fix same code section',
764
+ },
765
+ ],
766
+ },
767
+ ];
768
+ /**
769
+ * Global error registry instance.
770
+ * Read-only singleton initialized at module load.
771
+ */
772
+ export const ERROR_REGISTRY = new ErrorRegistryImpl(ERROR_DEFINITIONS);
773
+ // ============================================================
774
+ // TEMPLATE RENDERING
775
+ // ============================================================
776
+ /**
777
+ * Renders a message template by replacing placeholders with context values.
778
+ *
779
+ * Placeholder format: {varName}
780
+ * Missing context values render as empty string.
781
+ * Non-string values are coerced via String().
782
+ * Invalid templates (unclosed braces) return template unchanged.
783
+ *
784
+ * @param template - Template string with {placeholder} syntax
785
+ * @param context - Key-value pairs for placeholder replacement
786
+ * @returns Rendered message with placeholders replaced
787
+ *
788
+ * @example
789
+ * renderMessage("Expected {expected}, got {actual}", {expected: "string", actual: "number"})
790
+ * // Returns: "Expected string, got number"
791
+ *
792
+ * @example
793
+ * renderMessage("Hello {name}", {})
794
+ * // Returns: "Hello "
795
+ */
796
+ export function renderMessage(template, context) {
797
+ let result = '';
798
+ let i = 0;
799
+ while (i < template.length) {
800
+ const char = template[i];
801
+ if (char === '{') {
802
+ // Check if this is the start of a placeholder
803
+ const nextChar = template[i + 1];
804
+ if (nextChar !== '{') {
805
+ // Find the closing brace
806
+ let j = i + 1;
807
+ while (j < template.length && template[j] !== '}') {
808
+ j++;
809
+ }
810
+ // Check if we found a closing brace
811
+ if (j >= template.length) {
812
+ // Unclosed brace - return template unchanged
813
+ return template;
814
+ }
815
+ // Extract placeholder name and render value
816
+ const placeholderName = template.slice(i + 1, j);
817
+ const value = context[placeholderName];
818
+ // Render value: missing = empty string, non-string coerced via String()
819
+ if (value === undefined) {
820
+ result += '';
821
+ }
822
+ else {
823
+ try {
824
+ result += String(value);
825
+ }
826
+ catch {
827
+ // String() coercion failed - use default toString behavior
828
+ result += Object.prototype.toString.call(value);
829
+ }
830
+ }
831
+ // Move past closing brace. Each character is visited once (O(n) performance).
832
+ i = j + 1;
833
+ continue;
834
+ }
835
+ }
836
+ // Regular character - append to result
837
+ result += char;
838
+ i++;
839
+ }
840
+ return result;
841
+ }
842
+ /**
843
+ * Generates documentation URL for an error ID.
844
+ *
845
+ * Format: https://github.com/rcrsr/rill/blob/v{version}/docs/ref-errors.md#{errorId}
846
+ * Error ID is lowercased in anchor.
847
+ *
848
+ * @param errorId - Error identifier (format: RILL-{category}{3-digit}, e.g., RILL-R001)
849
+ * @param version - Semver version (format: X.Y.Z)
850
+ * @returns Documentation URL, or empty string if inputs are invalid
851
+ *
852
+ * @example
853
+ * getHelpUrl("RILL-R001", "0.4.1")
854
+ * // Returns: "https://github.com/rcrsr/rill/blob/v0.4.1/docs/ref-errors.md#rill-r001"
855
+ *
856
+ * @example
857
+ * getHelpUrl("invalid", "0.4.1")
858
+ * // Returns: ""
859
+ */
860
+ export function getHelpUrl(errorId, version) {
861
+ // Validate errorId format: RILL-{category}{3-digit}
862
+ // Category is single letter (L=lexer, P=parse, R=runtime, C=check)
863
+ const errorIdPattern = /^RILL-[LPRC]\d{3}$/;
864
+ if (!errorIdPattern.test(errorId)) {
865
+ return '';
866
+ }
867
+ // Validate version format: X.Y.Z (semver)
868
+ const versionPattern = /^\d+\.\d+\.\d+$/;
869
+ if (!versionPattern.test(version)) {
870
+ return '';
871
+ }
872
+ // Build URL with lowercased errorId in anchor
873
+ const anchor = errorId.toLowerCase();
874
+ return `https://github.com/rcrsr/rill/blob/v${version}/docs/ref-errors.md#${anchor}`;
875
+ }
876
+ //# sourceMappingURL=error-registry.js.map