binja 0.5.2 → 0.6.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/dist/cli.js +179 -65
- package/dist/debug/collector.d.ts +43 -0
- package/dist/debug/collector.d.ts.map +1 -1
- package/dist/debug/index.d.ts +2 -1
- package/dist/debug/index.d.ts.map +1 -1
- package/dist/debug/index.js +278 -1
- package/dist/debug/integrations.d.ts +104 -0
- package/dist/debug/integrations.d.ts.map +1 -0
- package/dist/errors/index.d.ts +65 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +438 -111
- package/dist/lexer/index.d.ts.map +1 -1
- package/dist/parser/index.d.ts +2 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -117,6 +117,82 @@ function tokenizeNative(source) {
|
|
|
117
117
|
return tokens;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
// src/errors/index.ts
|
|
121
|
+
var colors = {
|
|
122
|
+
red: "\x1B[31m",
|
|
123
|
+
yellow: "\x1B[33m",
|
|
124
|
+
cyan: "\x1B[36m",
|
|
125
|
+
gray: "\x1B[90m",
|
|
126
|
+
bold: "\x1B[1m",
|
|
127
|
+
dim: "\x1B[2m",
|
|
128
|
+
reset: "\x1B[0m"
|
|
129
|
+
};
|
|
130
|
+
var useColors = process.stdout?.isTTY !== false;
|
|
131
|
+
function c(color, text) {
|
|
132
|
+
return useColors ? `${colors[color]}${text}${colors.reset}` : text;
|
|
133
|
+
}
|
|
134
|
+
class TemplateSyntaxError extends Error {
|
|
135
|
+
line;
|
|
136
|
+
column;
|
|
137
|
+
source;
|
|
138
|
+
templateName;
|
|
139
|
+
suggestion;
|
|
140
|
+
constructor(message, options) {
|
|
141
|
+
const formatted = formatError("TemplateSyntaxError", message, options);
|
|
142
|
+
super(formatted);
|
|
143
|
+
this.name = "TemplateSyntaxError";
|
|
144
|
+
this.line = options.line;
|
|
145
|
+
this.column = options.column;
|
|
146
|
+
this.source = options.source;
|
|
147
|
+
this.templateName = options.templateName;
|
|
148
|
+
this.suggestion = options.suggestion;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function formatError(type, message, options) {
|
|
152
|
+
const parts = [];
|
|
153
|
+
const location = options.templateName ? `${options.templateName}:${options.line}:${options.column}` : `line ${options.line}, column ${options.column}`;
|
|
154
|
+
parts.push(`${c("red", c("bold", type))}: ${message} at ${c("cyan", location)}`);
|
|
155
|
+
if (options.source) {
|
|
156
|
+
parts.push("");
|
|
157
|
+
parts.push(generateSnippet(options.source, options.line, options.column));
|
|
158
|
+
}
|
|
159
|
+
if (options.suggestion) {
|
|
160
|
+
parts.push("");
|
|
161
|
+
parts.push(`${c("yellow", "Did you mean")}: ${c("cyan", options.suggestion)}?`);
|
|
162
|
+
}
|
|
163
|
+
if (options.availableOptions && options.availableOptions.length > 0) {
|
|
164
|
+
parts.push("");
|
|
165
|
+
const truncated = options.availableOptions.slice(0, 8);
|
|
166
|
+
const more = options.availableOptions.length > 8 ? ` ${c("gray", `... and ${options.availableOptions.length - 8} more`)}` : "";
|
|
167
|
+
parts.push(`${c("gray", "Available")}: ${truncated.join(", ")}${more}`);
|
|
168
|
+
}
|
|
169
|
+
return parts.join(`
|
|
170
|
+
`);
|
|
171
|
+
}
|
|
172
|
+
function generateSnippet(source, errorLine, errorColumn) {
|
|
173
|
+
const lines = source.split(`
|
|
174
|
+
`);
|
|
175
|
+
const parts = [];
|
|
176
|
+
const startLine = Math.max(1, errorLine - 2);
|
|
177
|
+
const endLine = Math.min(lines.length, errorLine + 1);
|
|
178
|
+
const gutterWidth = String(endLine).length;
|
|
179
|
+
for (let i = startLine;i <= endLine; i++) {
|
|
180
|
+
const lineContent = lines[i - 1] || "";
|
|
181
|
+
const lineNum = String(i).padStart(gutterWidth, " ");
|
|
182
|
+
const isErrorLine = i === errorLine;
|
|
183
|
+
if (isErrorLine) {
|
|
184
|
+
parts.push(`${c("red", " \u2192")} ${c("gray", lineNum)} ${c("dim", "\u2502")} ${lineContent}`);
|
|
185
|
+
const caretPadding = " ".repeat(gutterWidth + 4 + Math.max(0, errorColumn - 1));
|
|
186
|
+
const caret = c("red", "^");
|
|
187
|
+
parts.push(`${caretPadding}${caret}`);
|
|
188
|
+
} else {
|
|
189
|
+
parts.push(` ${c("gray", lineNum)} ${c("dim", "\u2502")} ${c("gray", lineContent)}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return parts.join(`
|
|
193
|
+
`);
|
|
194
|
+
}
|
|
195
|
+
|
|
120
196
|
// src/lexer/index.ts
|
|
121
197
|
class Lexer {
|
|
122
198
|
state;
|
|
@@ -204,7 +280,11 @@ class Lexer {
|
|
|
204
280
|
if (this.peek() === "-")
|
|
205
281
|
this.advance();
|
|
206
282
|
if (!this.match(this.blockEnd)) {
|
|
207
|
-
throw new
|
|
283
|
+
throw new TemplateSyntaxError(`Expected '${this.blockEnd}' after '${tagName}'`, {
|
|
284
|
+
line: this.state.line,
|
|
285
|
+
column: this.state.column,
|
|
286
|
+
source: this.state.source
|
|
287
|
+
});
|
|
208
288
|
}
|
|
209
289
|
const endTag = `end${tagName}`;
|
|
210
290
|
const contentStart = this.state.pos;
|
|
@@ -234,7 +314,11 @@ class Lexer {
|
|
|
234
314
|
if (this.peek() === "-")
|
|
235
315
|
this.advance();
|
|
236
316
|
if (!this.match(this.blockEnd)) {
|
|
237
|
-
throw new
|
|
317
|
+
throw new TemplateSyntaxError(`Expected '${this.blockEnd}' after '${endTag}'`, {
|
|
318
|
+
line: this.state.line,
|
|
319
|
+
column: this.state.column,
|
|
320
|
+
source: this.state.source
|
|
321
|
+
});
|
|
238
322
|
}
|
|
239
323
|
return;
|
|
240
324
|
}
|
|
@@ -249,7 +333,12 @@ class Lexer {
|
|
|
249
333
|
}
|
|
250
334
|
this.advance();
|
|
251
335
|
}
|
|
252
|
-
throw new
|
|
336
|
+
throw new TemplateSyntaxError(`Unclosed '${tagName}' block`, {
|
|
337
|
+
line: startLine,
|
|
338
|
+
column: startColumn,
|
|
339
|
+
source: this.state.source,
|
|
340
|
+
suggestion: `Add {% end${tagName} %} to close the block`
|
|
341
|
+
});
|
|
253
342
|
}
|
|
254
343
|
scanText() {
|
|
255
344
|
const start = this.state.pos;
|
|
@@ -289,22 +378,27 @@ class Lexer {
|
|
|
289
378
|
}
|
|
290
379
|
this.scanExpressionToken();
|
|
291
380
|
}
|
|
292
|
-
throw new
|
|
381
|
+
throw new TemplateSyntaxError(`Unclosed template tag`, {
|
|
382
|
+
line: this.state.line,
|
|
383
|
+
column: this.state.column,
|
|
384
|
+
source: this.state.source,
|
|
385
|
+
suggestion: `Add closing delimiter '${endDelimiter}'`
|
|
386
|
+
});
|
|
293
387
|
}
|
|
294
388
|
scanExpressionToken() {
|
|
295
389
|
this.skipWhitespace();
|
|
296
390
|
if (this.isAtEnd())
|
|
297
391
|
return;
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
this.scanString(
|
|
392
|
+
const c2 = this.peek();
|
|
393
|
+
if (c2 === '"' || c2 === "'") {
|
|
394
|
+
this.scanString(c2);
|
|
301
395
|
return;
|
|
302
396
|
}
|
|
303
|
-
if (this.isDigit(
|
|
397
|
+
if (this.isDigit(c2)) {
|
|
304
398
|
this.scanNumber();
|
|
305
399
|
return;
|
|
306
400
|
}
|
|
307
|
-
if (this.isAlpha(
|
|
401
|
+
if (this.isAlpha(c2) || c2 === "_") {
|
|
308
402
|
this.scanIdentifier();
|
|
309
403
|
return;
|
|
310
404
|
}
|
|
@@ -325,7 +419,12 @@ class Lexer {
|
|
|
325
419
|
this.advance();
|
|
326
420
|
}
|
|
327
421
|
if (this.isAtEnd()) {
|
|
328
|
-
throw new
|
|
422
|
+
throw new TemplateSyntaxError(`Unterminated string literal`, {
|
|
423
|
+
line: this.state.line,
|
|
424
|
+
column: this.state.column,
|
|
425
|
+
source: this.state.source,
|
|
426
|
+
suggestion: `Add closing quote '${quote}'`
|
|
427
|
+
});
|
|
329
428
|
}
|
|
330
429
|
const value = this.state.source.slice(start, this.state.pos);
|
|
331
430
|
this.advance();
|
|
@@ -355,55 +454,55 @@ class Lexer {
|
|
|
355
454
|
this.addToken(type, value);
|
|
356
455
|
}
|
|
357
456
|
scanOperator() {
|
|
358
|
-
const
|
|
359
|
-
switch (
|
|
457
|
+
const c2 = this.advance();
|
|
458
|
+
switch (c2) {
|
|
360
459
|
case ".":
|
|
361
|
-
this.addToken("DOT" /* DOT */,
|
|
460
|
+
this.addToken("DOT" /* DOT */, c2);
|
|
362
461
|
break;
|
|
363
462
|
case ",":
|
|
364
|
-
this.addToken("COMMA" /* COMMA */,
|
|
463
|
+
this.addToken("COMMA" /* COMMA */, c2);
|
|
365
464
|
break;
|
|
366
465
|
case ":":
|
|
367
|
-
this.addToken("COLON" /* COLON */,
|
|
466
|
+
this.addToken("COLON" /* COLON */, c2);
|
|
368
467
|
break;
|
|
369
468
|
case "|":
|
|
370
|
-
this.addToken("PIPE" /* PIPE */,
|
|
469
|
+
this.addToken("PIPE" /* PIPE */, c2);
|
|
371
470
|
break;
|
|
372
471
|
case "(":
|
|
373
|
-
this.addToken("LPAREN" /* LPAREN */,
|
|
472
|
+
this.addToken("LPAREN" /* LPAREN */, c2);
|
|
374
473
|
break;
|
|
375
474
|
case ")":
|
|
376
|
-
this.addToken("RPAREN" /* RPAREN */,
|
|
475
|
+
this.addToken("RPAREN" /* RPAREN */, c2);
|
|
377
476
|
break;
|
|
378
477
|
case "[":
|
|
379
|
-
this.addToken("LBRACKET" /* LBRACKET */,
|
|
478
|
+
this.addToken("LBRACKET" /* LBRACKET */, c2);
|
|
380
479
|
break;
|
|
381
480
|
case "]":
|
|
382
|
-
this.addToken("RBRACKET" /* RBRACKET */,
|
|
481
|
+
this.addToken("RBRACKET" /* RBRACKET */, c2);
|
|
383
482
|
break;
|
|
384
483
|
case "{":
|
|
385
|
-
this.addToken("LBRACE" /* LBRACE */,
|
|
484
|
+
this.addToken("LBRACE" /* LBRACE */, c2);
|
|
386
485
|
break;
|
|
387
486
|
case "}":
|
|
388
|
-
this.addToken("RBRACE" /* RBRACE */,
|
|
487
|
+
this.addToken("RBRACE" /* RBRACE */, c2);
|
|
389
488
|
break;
|
|
390
489
|
case "+":
|
|
391
|
-
this.addToken("ADD" /* ADD */,
|
|
490
|
+
this.addToken("ADD" /* ADD */, c2);
|
|
392
491
|
break;
|
|
393
492
|
case "-":
|
|
394
|
-
this.addToken("SUB" /* SUB */,
|
|
493
|
+
this.addToken("SUB" /* SUB */, c2);
|
|
395
494
|
break;
|
|
396
495
|
case "*":
|
|
397
|
-
this.addToken("MUL" /* MUL */,
|
|
496
|
+
this.addToken("MUL" /* MUL */, c2);
|
|
398
497
|
break;
|
|
399
498
|
case "/":
|
|
400
|
-
this.addToken("DIV" /* DIV */,
|
|
499
|
+
this.addToken("DIV" /* DIV */, c2);
|
|
401
500
|
break;
|
|
402
501
|
case "%":
|
|
403
|
-
this.addToken("MOD" /* MOD */,
|
|
502
|
+
this.addToken("MOD" /* MOD */, c2);
|
|
404
503
|
break;
|
|
405
504
|
case "~":
|
|
406
|
-
this.addToken("TILDE" /* TILDE */,
|
|
505
|
+
this.addToken("TILDE" /* TILDE */, c2);
|
|
407
506
|
break;
|
|
408
507
|
case "=":
|
|
409
508
|
if (this.match("=")) {
|
|
@@ -416,7 +515,12 @@ class Lexer {
|
|
|
416
515
|
if (this.match("=")) {
|
|
417
516
|
this.addToken("NE" /* NE */, "!=");
|
|
418
517
|
} else {
|
|
419
|
-
throw new
|
|
518
|
+
throw new TemplateSyntaxError(`Unexpected character '!'`, {
|
|
519
|
+
line: this.state.line,
|
|
520
|
+
column: this.state.column - 1,
|
|
521
|
+
source: this.state.source,
|
|
522
|
+
suggestion: `Use '!=' for not-equal comparison or 'not' for negation`
|
|
523
|
+
});
|
|
420
524
|
}
|
|
421
525
|
break;
|
|
422
526
|
case "<":
|
|
@@ -434,8 +538,12 @@ class Lexer {
|
|
|
434
538
|
}
|
|
435
539
|
break;
|
|
436
540
|
default:
|
|
437
|
-
if (!this.isWhitespace(
|
|
438
|
-
throw new
|
|
541
|
+
if (!this.isWhitespace(c2)) {
|
|
542
|
+
throw new TemplateSyntaxError(`Unexpected character '${c2}'`, {
|
|
543
|
+
line: this.state.line,
|
|
544
|
+
column: this.state.column - 1,
|
|
545
|
+
source: this.state.source
|
|
546
|
+
});
|
|
439
547
|
}
|
|
440
548
|
}
|
|
441
549
|
}
|
|
@@ -466,10 +574,10 @@ class Lexer {
|
|
|
466
574
|
return this.state.source[this.state.pos + 1];
|
|
467
575
|
}
|
|
468
576
|
advance() {
|
|
469
|
-
const
|
|
577
|
+
const c2 = this.state.source[this.state.pos];
|
|
470
578
|
this.state.pos++;
|
|
471
579
|
this.state.column++;
|
|
472
|
-
return
|
|
580
|
+
return c2;
|
|
473
581
|
}
|
|
474
582
|
match(expected, offset = 0) {
|
|
475
583
|
const source = this.state.source;
|
|
@@ -509,20 +617,20 @@ class Lexer {
|
|
|
509
617
|
this.advance();
|
|
510
618
|
}
|
|
511
619
|
}
|
|
512
|
-
isWhitespace(
|
|
513
|
-
return
|
|
514
|
-
` ||
|
|
620
|
+
isWhitespace(c2) {
|
|
621
|
+
return c2 === " " || c2 === "\t" || c2 === `
|
|
622
|
+
` || c2 === "\r";
|
|
515
623
|
}
|
|
516
|
-
isDigit(
|
|
517
|
-
const code =
|
|
624
|
+
isDigit(c2) {
|
|
625
|
+
const code = c2.charCodeAt(0);
|
|
518
626
|
return code >= 48 && code <= 57;
|
|
519
627
|
}
|
|
520
|
-
isAlpha(
|
|
521
|
-
const code =
|
|
628
|
+
isAlpha(c2) {
|
|
629
|
+
const code = c2.charCodeAt(0);
|
|
522
630
|
return code >= 97 && code <= 122 || code >= 65 && code <= 90;
|
|
523
631
|
}
|
|
524
|
-
isAlphaNumeric(
|
|
525
|
-
const code =
|
|
632
|
+
isAlphaNumeric(c2) {
|
|
633
|
+
const code = c2.charCodeAt(0);
|
|
526
634
|
return code >= 48 && code <= 57 || code >= 97 && code <= 122 || code >= 65 && code <= 90;
|
|
527
635
|
}
|
|
528
636
|
addToken(type, value) {
|
|
@@ -539,8 +647,10 @@ class Lexer {
|
|
|
539
647
|
class Parser {
|
|
540
648
|
tokens;
|
|
541
649
|
current = 0;
|
|
542
|
-
|
|
650
|
+
source;
|
|
651
|
+
constructor(tokens, source) {
|
|
543
652
|
this.tokens = tokens;
|
|
653
|
+
this.source = source;
|
|
544
654
|
}
|
|
545
655
|
parse() {
|
|
546
656
|
const body = [];
|
|
@@ -1632,7 +1742,11 @@ class Parser {
|
|
|
1632
1742
|
}
|
|
1633
1743
|
error(message) {
|
|
1634
1744
|
const token = this.peek();
|
|
1635
|
-
return new
|
|
1745
|
+
return new TemplateSyntaxError(message, {
|
|
1746
|
+
line: token.line,
|
|
1747
|
+
column: token.column,
|
|
1748
|
+
source: this.source
|
|
1749
|
+
});
|
|
1636
1750
|
}
|
|
1637
1751
|
}
|
|
1638
1752
|
|
|
@@ -2316,7 +2430,7 @@ class StaticChecker {
|
|
|
2316
2430
|
|
|
2317
2431
|
// src/cli.ts
|
|
2318
2432
|
var VERSION = "0.1.1";
|
|
2319
|
-
var
|
|
2433
|
+
var colors2 = {
|
|
2320
2434
|
reset: "\x1B[0m",
|
|
2321
2435
|
green: "\x1B[32m",
|
|
2322
2436
|
yellow: "\x1B[33m",
|
|
@@ -2328,25 +2442,25 @@ function log(msg) {
|
|
|
2328
2442
|
console.log(msg);
|
|
2329
2443
|
}
|
|
2330
2444
|
function success(msg) {
|
|
2331
|
-
console.log(`${
|
|
2445
|
+
console.log(`${colors2.green}\u2713${colors2.reset} ${msg}`);
|
|
2332
2446
|
}
|
|
2333
2447
|
function warn(msg) {
|
|
2334
|
-
console.log(`${
|
|
2448
|
+
console.log(`${colors2.yellow}\u26A0${colors2.reset} ${msg}`);
|
|
2335
2449
|
}
|
|
2336
2450
|
function error(msg) {
|
|
2337
|
-
console.error(`${
|
|
2451
|
+
console.error(`${colors2.red}\u2717${colors2.reset} ${msg}`);
|
|
2338
2452
|
}
|
|
2339
2453
|
function printHelp() {
|
|
2340
2454
|
console.log(`
|
|
2341
|
-
${
|
|
2455
|
+
${colors2.cyan}binja${colors2.reset} - High-performance template compiler
|
|
2342
2456
|
|
|
2343
|
-
${
|
|
2457
|
+
${colors2.yellow}Usage:${colors2.reset}
|
|
2344
2458
|
binja compile <source> [options] Compile templates to JavaScript
|
|
2345
2459
|
binja check <source> Check if templates can be AOT compiled
|
|
2346
2460
|
binja --help Show this help
|
|
2347
2461
|
binja --version Show version
|
|
2348
2462
|
|
|
2349
|
-
${
|
|
2463
|
+
${colors2.yellow}Compile Options:${colors2.reset}
|
|
2350
2464
|
-o, --output <dir> Output directory (required)
|
|
2351
2465
|
-n, --name <name> Function name for single file compilation
|
|
2352
2466
|
-m, --minify Minify output
|
|
@@ -2354,26 +2468,26 @@ ${colors.yellow}Compile Options:${colors.reset}
|
|
|
2354
2468
|
-v, --verbose Verbose output
|
|
2355
2469
|
-w, --watch Watch for changes and recompile
|
|
2356
2470
|
|
|
2357
|
-
${
|
|
2358
|
-
${
|
|
2471
|
+
${colors2.yellow}Examples:${colors2.reset}
|
|
2472
|
+
${colors2.dim}# Compile all templates in a directory${colors2.reset}
|
|
2359
2473
|
binja compile ./templates -o ./dist/templates
|
|
2360
2474
|
|
|
2361
|
-
${
|
|
2475
|
+
${colors2.dim}# Compile with minification${colors2.reset}
|
|
2362
2476
|
binja compile ./views -o ./compiled --minify
|
|
2363
2477
|
|
|
2364
|
-
${
|
|
2478
|
+
${colors2.dim}# Compile single file with custom function name${colors2.reset}
|
|
2365
2479
|
binja compile ./templates/home.html -o ./dist --name renderHome
|
|
2366
2480
|
|
|
2367
|
-
${
|
|
2481
|
+
${colors2.dim}# Watch mode for development${colors2.reset}
|
|
2368
2482
|
binja compile ./templates -o ./dist --watch
|
|
2369
2483
|
|
|
2370
|
-
${
|
|
2484
|
+
${colors2.yellow}Output:${colors2.reset}
|
|
2371
2485
|
Generated files export a render function:
|
|
2372
2486
|
|
|
2373
|
-
${
|
|
2487
|
+
${colors2.dim}// dist/templates/home.js${colors2.reset}
|
|
2374
2488
|
export function render(ctx) { ... }
|
|
2375
2489
|
|
|
2376
|
-
${
|
|
2490
|
+
${colors2.dim}// Usage${colors2.reset}
|
|
2377
2491
|
import { render } from './dist/templates/home.js'
|
|
2378
2492
|
const html = render({ title: 'Hello' })
|
|
2379
2493
|
`);
|
|
@@ -2502,7 +2616,7 @@ async function compileFile(filePath, outputDir, baseDir, options) {
|
|
|
2502
2616
|
finalAst = flattenTemplate(ast, { loader });
|
|
2503
2617
|
}
|
|
2504
2618
|
const relativePath = path.relative(baseDir, filePath);
|
|
2505
|
-
const functionName = options.name || "render" + relativePath.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9]/g, "_").replace(/^_+|_+$/g, "").replace(/_([a-z])/g, (_,
|
|
2619
|
+
const functionName = options.name || "render" + relativePath.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9]/g, "_").replace(/^_+|_+$/g, "").replace(/_([a-z])/g, (_, c2) => c2.toUpperCase());
|
|
2506
2620
|
const code = compileToString(finalAst, {
|
|
2507
2621
|
functionName,
|
|
2508
2622
|
minify: options.minify
|
|
@@ -2591,14 +2705,14 @@ async function checkTemplates(sourceDir, options) {
|
|
|
2591
2705
|
walkDir(sourceDir);
|
|
2592
2706
|
log("");
|
|
2593
2707
|
log(`Total: ${total} templates`);
|
|
2594
|
-
log(`${
|
|
2708
|
+
log(`${colors2.green}AOT compatible: ${canCompile}${colors2.reset}`);
|
|
2595
2709
|
if (cannotCompile > 0) {
|
|
2596
|
-
log(`${
|
|
2710
|
+
log(`${colors2.yellow}Require runtime: ${cannotCompile}${colors2.reset}`);
|
|
2597
2711
|
}
|
|
2598
2712
|
}
|
|
2599
2713
|
async function watchAndCompile(sourceDir, outputDir, options) {
|
|
2600
|
-
log(`${
|
|
2601
|
-
log(`${
|
|
2714
|
+
log(`${colors2.cyan}Watching${colors2.reset} ${sourceDir} for changes...`);
|
|
2715
|
+
log(`${colors2.dim}Press Ctrl+C to stop${colors2.reset}`);
|
|
2602
2716
|
log("");
|
|
2603
2717
|
const { compiled, failed } = await compileDirectory(sourceDir, outputDir, { ...options, verbose: true });
|
|
2604
2718
|
log("");
|
|
@@ -2613,7 +2727,7 @@ async function watchAndCompile(sourceDir, outputDir, options) {
|
|
|
2613
2727
|
const fullPath = path.join(sourceDir, filename);
|
|
2614
2728
|
if (!fs.existsSync(fullPath))
|
|
2615
2729
|
return;
|
|
2616
|
-
log(`${
|
|
2730
|
+
log(`${colors2.dim}[${new Date().toLocaleTimeString()}]${colors2.reset} ${filename} changed`);
|
|
2617
2731
|
const result = await compileFile(fullPath, outputDir, sourceDir, options);
|
|
2618
2732
|
if (result.success) {
|
|
2619
2733
|
success(`Compiled ${filename}`);
|
|
@@ -18,6 +18,34 @@ export interface ContextValue {
|
|
|
18
18
|
expandable: boolean;
|
|
19
19
|
children?: Record<string, ContextValue>;
|
|
20
20
|
}
|
|
21
|
+
export interface QueryInfo {
|
|
22
|
+
/** SQL query or operation name */
|
|
23
|
+
sql: string;
|
|
24
|
+
/** Query parameters */
|
|
25
|
+
params?: any[];
|
|
26
|
+
/** Duration in milliseconds */
|
|
27
|
+
duration: number;
|
|
28
|
+
/** Number of rows returned */
|
|
29
|
+
rows?: number;
|
|
30
|
+
/** Source ORM (drizzle, prisma, etc.) */
|
|
31
|
+
source?: string;
|
|
32
|
+
/** Timestamp when query was executed */
|
|
33
|
+
timestamp: number;
|
|
34
|
+
/** Whether this query was detected as part of N+1 */
|
|
35
|
+
isN1?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface QueryStats {
|
|
38
|
+
/** Total number of queries */
|
|
39
|
+
count: number;
|
|
40
|
+
/** Total duration of all queries */
|
|
41
|
+
totalDuration: number;
|
|
42
|
+
/** Number of slow queries (> 100ms) */
|
|
43
|
+
slowCount: number;
|
|
44
|
+
/** Number of N+1 queries detected */
|
|
45
|
+
n1Count: number;
|
|
46
|
+
/** Queries grouped by similar SQL for N+1 detection */
|
|
47
|
+
queryCounts: Map<string, number>;
|
|
48
|
+
}
|
|
21
49
|
export interface DebugData {
|
|
22
50
|
startTime: number;
|
|
23
51
|
endTime?: number;
|
|
@@ -35,6 +63,8 @@ export interface DebugData {
|
|
|
35
63
|
testsUsed: Map<string, number>;
|
|
36
64
|
cacheHits: number;
|
|
37
65
|
cacheMisses: number;
|
|
66
|
+
queries: QueryInfo[];
|
|
67
|
+
queryStats: QueryStats;
|
|
38
68
|
warnings: string[];
|
|
39
69
|
}
|
|
40
70
|
export declare class DebugCollector {
|
|
@@ -59,6 +89,19 @@ export declare class DebugCollector {
|
|
|
59
89
|
recordCacheHit(): void;
|
|
60
90
|
recordCacheMiss(): void;
|
|
61
91
|
addWarning(message: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* Record a database query for telemetry
|
|
94
|
+
* @param query Query information
|
|
95
|
+
*/
|
|
96
|
+
recordQuery(query: Omit<QueryInfo, 'timestamp' | 'isN1'>): void;
|
|
97
|
+
/**
|
|
98
|
+
* Normalize SQL query for comparison (removes specific values)
|
|
99
|
+
*/
|
|
100
|
+
private normalizeQuery;
|
|
101
|
+
/**
|
|
102
|
+
* Get query statistics
|
|
103
|
+
*/
|
|
104
|
+
getQueryStats(): QueryStats;
|
|
62
105
|
getData(): DebugData;
|
|
63
106
|
getSummary(): {
|
|
64
107
|
totalTime: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/debug/collector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,GAAG,CAAA;IACV,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACxC;AAED,MAAM,WAAW,SAAS;IAExB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IAGnB,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IAGrB,IAAI,EAAE,SAAS,GAAG,KAAK,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAGhB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAG7C,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAG9B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IAGnB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAAW;;
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/debug/collector.ts"],"names":[],"mappings":"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"}
|
package/dist/debug/index.d.ts
CHANGED
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
import type { Environment } from '../index';
|
|
14
14
|
import { PanelOptions } from './panel';
|
|
15
15
|
export { DebugCollector, startDebugCollection, endDebugCollection, getDebugCollector } from './collector';
|
|
16
|
-
export type { DebugData, ContextValue } from './collector';
|
|
16
|
+
export type { DebugData, ContextValue, QueryInfo, QueryStats } from './collector';
|
|
17
17
|
export { generateDebugPanel } from './panel';
|
|
18
18
|
export type { PanelOptions } from './panel';
|
|
19
|
+
export { recordQuery, createPrismaMiddleware, setupPrismaLogging, createDrizzleLogger, wrapDrizzleQuery, wrapBunSQL, wrapQuery, createQueryWrapper, } from './integrations';
|
|
19
20
|
export interface DebugRenderOptions {
|
|
20
21
|
/** Panel options */
|
|
21
22
|
panel?: PanelOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/debug/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,EAAsB,YAAY,EAAE,MAAM,SAAS,CAAA;AAG1D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACzG,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/debug/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,EAAsB,YAAY,EAAE,MAAM,SAAS,CAAA;AAG1D,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACzG,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAG3C,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,GAAE,kBAAuB;yBAEvD,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAQ,OAAO,CAAC,MAAM,CAAC;yBAG3D,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAQ,OAAO,CAAC,MAAM,CAAC;EAIzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,GAAE,kBAAuB;IAE9E;;OAEG;aAEa,GAAG,GAAG,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC;IAyBjD;;OAEG;gBAEO,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,IAAI;EA2BjD"}
|