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.
@@ -14,6 +14,14 @@ class DebugCollector {
14
14
  testsUsed: new Map,
15
15
  cacheHits: 0,
16
16
  cacheMisses: 0,
17
+ queries: [],
18
+ queryStats: {
19
+ count: 0,
20
+ totalDuration: 0,
21
+ slowCount: 0,
22
+ n1Count: 0,
23
+ queryCounts: new Map
24
+ },
17
25
  warnings: []
18
26
  };
19
27
  }
@@ -154,6 +162,33 @@ class DebugCollector {
154
162
  addWarning(message) {
155
163
  this.data.warnings.push(message);
156
164
  }
165
+ recordQuery(query) {
166
+ const normalizedSql = this.normalizeQuery(query.sql);
167
+ const currentCount = this.data.queryStats.queryCounts.get(normalizedSql) || 0;
168
+ this.data.queryStats.queryCounts.set(normalizedSql, currentCount + 1);
169
+ const isN1 = currentCount >= 2;
170
+ const queryInfo = {
171
+ ...query,
172
+ timestamp: performance.now(),
173
+ isN1
174
+ };
175
+ this.data.queries.push(queryInfo);
176
+ this.data.queryStats.count++;
177
+ this.data.queryStats.totalDuration += query.duration;
178
+ if (query.duration > 100) {
179
+ this.data.queryStats.slowCount++;
180
+ }
181
+ if (isN1 && currentCount === 2) {
182
+ this.data.queryStats.n1Count++;
183
+ this.addWarning(`N+1 query detected: ${normalizedSql.slice(0, 50)}...`);
184
+ }
185
+ }
186
+ normalizeQuery(sql) {
187
+ return sql.replace(/\s+/g, " ").replace(/= \?/g, "= ?").replace(/= \$\d+/g, "= ?").replace(/= '\w+'/g, "= '?'").replace(/= \d+/g, "= ?").replace(/IN \([^)]+\)/gi, "IN (?)").trim();
188
+ }
189
+ getQueryStats() {
190
+ return this.data.queryStats;
191
+ }
157
192
  getData() {
158
193
  return this.data;
159
194
  }
@@ -315,6 +350,25 @@ function generateStyles(id, c, opts) {
315
350
  #${id} .dbg-warning { display: flex; align-items: flex-start; gap: 8px; padding: 10px 12px; background: rgba(234,179,8,0.1); border-radius: 6px; border-left: 3px solid ${c.warning}; }
316
351
  #${id} .dbg-warning-icon { color: ${c.warning}; flex-shrink: 0; margin-top: 1px; }
317
352
  #${id} .dbg-warning-text { color: ${c.text}; font-size: 12px; }
353
+ #${id} .dbg-queries { display: flex; flex-direction: column; gap: 8px; }
354
+ #${id} .dbg-query { background: ${c.bg}; border-radius: 6px; overflow: hidden; }
355
+ #${id} .dbg-query.n1 { border-left: 3px solid ${c.error}; }
356
+ #${id} .dbg-query.slow { border-left: 3px solid ${c.warning}; }
357
+ #${id} .dbg-query-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; gap: 8px; }
358
+ #${id} .dbg-query-sql { flex: 1; font-family: 'SF Mono', Monaco, monospace; font-size: 11px; color: ${c.text}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
359
+ #${id} .dbg-query-meta { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
360
+ #${id} .dbg-query-time { font-family: 'SF Mono', Monaco, monospace; font-size: 10px; padding: 2px 6px; border-radius: 3px; background: ${c.bgTertiary}; }
361
+ #${id} .dbg-query-time.slow { background: rgba(234,179,8,0.15); color: ${c.warning}; }
362
+ #${id} .dbg-query-rows { font-size: 10px; color: ${c.textMuted}; }
363
+ #${id} .dbg-query-source { font-size: 9px; padding: 2px 5px; border-radius: 3px; background: rgba(59,130,246,0.1); color: ${c.accent}; text-transform: uppercase; }
364
+ #${id} .dbg-query-badge { font-size: 9px; padding: 2px 5px; border-radius: 3px; font-weight: 600; }
365
+ #${id} .dbg-query-badge.n1 { background: rgba(239,68,68,0.15); color: ${c.error}; }
366
+ #${id} .dbg-query-stats { display: flex; gap: 12px; margin-bottom: 12px; padding: 10px; background: ${c.bg}; border-radius: 6px; }
367
+ #${id} .dbg-query-stat { flex: 1; text-align: center; }
368
+ #${id} .dbg-query-stat-num { font-size: 18px; font-weight: 600; font-family: 'SF Mono', Monaco, monospace; color: ${c.text}; }
369
+ #${id} .dbg-query-stat-num.warning { color: ${c.warning}; }
370
+ #${id} .dbg-query-stat-num.error { color: ${c.error}; }
371
+ #${id} .dbg-query-stat-label { font-size: 10px; color: ${c.textMuted}; margin-top: 2px; }
318
372
  `;
319
373
  }
320
374
  function getPosition(pos) {
@@ -339,7 +393,8 @@ var icons = {
339
393
  filter: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>`,
340
394
  cache: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2a10 10 0 1010 10H12V2z"/><path d="M12 2a10 10 0 00-8.66 15"/></svg>`,
341
395
  warning: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`,
342
- file: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"/></svg>`
396
+ file: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"/></svg>`,
397
+ database: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>`
343
398
  };
344
399
  function generateToggle(id, data, c) {
345
400
  const time = (data.totalTime || 0).toFixed(1);
@@ -368,6 +423,7 @@ function generatePanel(id, data, c, opts) {
368
423
  ${generateTemplatesSection(data)}
369
424
  ${generateContextSection(data)}
370
425
  ${generateFiltersSection(data)}
426
+ ${generateQueriesSection(data)}
371
427
  ${generateCacheSection(data)}
372
428
  ${generateWarningsSection(data)}
373
429
  </div>
@@ -531,6 +587,70 @@ function generateWarningsSection(data) {
531
587
  </div>
532
588
  </div>`;
533
589
  }
590
+ function generateQueriesSection(data) {
591
+ if (data.queries.length === 0)
592
+ return "";
593
+ const stats = data.queryStats;
594
+ const hasIssues = stats.slowCount > 0 || stats.n1Count > 0;
595
+ const statsHtml = `
596
+ <div class="dbg-query-stats">
597
+ <div class="dbg-query-stat">
598
+ <div class="dbg-query-stat-num">${stats.count}</div>
599
+ <div class="dbg-query-stat-label">Queries</div>
600
+ </div>
601
+ <div class="dbg-query-stat">
602
+ <div class="dbg-query-stat-num">${stats.totalDuration.toFixed(1)}ms</div>
603
+ <div class="dbg-query-stat-label">Total Time</div>
604
+ </div>
605
+ <div class="dbg-query-stat">
606
+ <div class="dbg-query-stat-num ${stats.slowCount > 0 ? "warning" : ""}">${stats.slowCount}</div>
607
+ <div class="dbg-query-stat-label">Slow (&gt;100ms)</div>
608
+ </div>
609
+ <div class="dbg-query-stat">
610
+ <div class="dbg-query-stat-num ${stats.n1Count > 0 ? "error" : ""}">${stats.n1Count}</div>
611
+ <div class="dbg-query-stat-label">N+1</div>
612
+ </div>
613
+ </div>`;
614
+ const queries = data.queries.map((q) => {
615
+ const isSlow = q.duration > 100;
616
+ const classes = [
617
+ "dbg-query",
618
+ q.isN1 ? "n1" : "",
619
+ isSlow ? "slow" : ""
620
+ ].filter(Boolean).join(" ");
621
+ const badges = [];
622
+ if (q.isN1) {
623
+ badges.push('<span class="dbg-query-badge n1">N+1</span>');
624
+ }
625
+ const rowsText = q.rows !== undefined ? `<span class="dbg-query-rows">${q.rows} rows</span>` : "";
626
+ const sourceText = q.source ? `<span class="dbg-query-source">${escapeHtml(q.source)}</span>` : "";
627
+ return `
628
+ <div class="${classes}">
629
+ <div class="dbg-query-header">
630
+ <span class="dbg-query-sql" title="${escapeHtml(q.sql)}">${escapeHtml(q.sql)}</span>
631
+ <div class="dbg-query-meta">
632
+ ${badges.join("")}
633
+ ${sourceText}
634
+ ${rowsText}
635
+ <span class="dbg-query-time ${isSlow ? "slow" : ""}">${q.duration.toFixed(1)}ms</span>
636
+ </div>
637
+ </div>
638
+ </div>`;
639
+ }).join("");
640
+ const metaColor = hasIssues ? 'style="color:#ef4444"' : "";
641
+ return `
642
+ <div class="dbg-section ${hasIssues ? "open" : ""}">
643
+ <div class="dbg-section-header" onclick="this.parentElement.classList.toggle('open')">
644
+ <span class="dbg-section-title">${icons.database} Queries</span>
645
+ <span class="dbg-section-meta" ${metaColor}>${stats.count} (${stats.totalDuration.toFixed(1)}ms)</span>
646
+ <span class="dbg-chevron">${icons.chevron}</span>
647
+ </div>
648
+ <div class="dbg-section-content">
649
+ ${statsHtml}
650
+ <div class="dbg-queries">${queries}</div>
651
+ </div>
652
+ </div>`;
653
+ }
534
654
  function generateScript(id) {
535
655
  return `
536
656
  (function(){
@@ -568,6 +688,155 @@ function generateScript(id) {
568
688
  function escapeHtml(str) {
569
689
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
570
690
  }
691
+ // src/debug/integrations.ts
692
+ function recordQuery(query) {
693
+ const collector = getDebugCollector();
694
+ if (collector) {
695
+ collector.recordQuery(query);
696
+ }
697
+ }
698
+ function createPrismaMiddleware() {
699
+ return async (params, next) => {
700
+ const collector = getDebugCollector();
701
+ const start = performance.now();
702
+ const result = await next(params);
703
+ const duration = performance.now() - start;
704
+ if (collector) {
705
+ const sql = `${params.action} ${params.model}`;
706
+ collector.recordQuery({
707
+ sql,
708
+ params: params.args ? [JSON.stringify(params.args)] : undefined,
709
+ duration,
710
+ rows: Array.isArray(result) ? result.length : result ? 1 : 0,
711
+ source: "prisma"
712
+ });
713
+ }
714
+ return result;
715
+ };
716
+ }
717
+ function setupPrismaLogging(prisma) {
718
+ prisma.$on("query", (e) => {
719
+ const collector = getDebugCollector();
720
+ if (collector) {
721
+ collector.recordQuery({
722
+ sql: e.query,
723
+ params: e.params ? JSON.parse(e.params) : undefined,
724
+ duration: e.duration,
725
+ source: "prisma"
726
+ });
727
+ }
728
+ });
729
+ }
730
+ function createDrizzleLogger() {
731
+ return {
732
+ logQuery(query, params) {
733
+ const collector = getDebugCollector();
734
+ if (collector) {
735
+ collector.recordQuery({
736
+ sql: query,
737
+ params,
738
+ duration: 0,
739
+ source: "drizzle"
740
+ });
741
+ }
742
+ }
743
+ };
744
+ }
745
+ async function wrapDrizzleQuery(query, sql) {
746
+ const collector = getDebugCollector();
747
+ const start = performance.now();
748
+ const result = await query;
749
+ const duration = performance.now() - start;
750
+ if (collector) {
751
+ collector.recordQuery({
752
+ sql: sql || "Drizzle Query",
753
+ duration,
754
+ rows: Array.isArray(result) ? result.length : result ? 1 : 0,
755
+ source: "drizzle"
756
+ });
757
+ }
758
+ return result;
759
+ }
760
+ function wrapBunSQL(db) {
761
+ const handler = {
762
+ get(target, prop) {
763
+ const value = target[prop];
764
+ if (typeof value === "function") {
765
+ if (prop === "query" || prop === "run" || prop === "prepare") {
766
+ return function(...args) {
767
+ const collector = getDebugCollector();
768
+ const sql = typeof args[0] === "string" ? args[0] : "SQL Query";
769
+ const start = performance.now();
770
+ const result = value.apply(target, args);
771
+ if (result && typeof result.all === "function") {
772
+ return wrapPreparedStatement(result, sql);
773
+ }
774
+ const duration = performance.now() - start;
775
+ if (collector) {
776
+ collector.recordQuery({
777
+ sql,
778
+ params: args.slice(1),
779
+ duration,
780
+ rows: Array.isArray(result) ? result.length : undefined,
781
+ source: "bun:sqlite"
782
+ });
783
+ }
784
+ return result;
785
+ };
786
+ }
787
+ }
788
+ return value;
789
+ }
790
+ };
791
+ return new Proxy(db, handler);
792
+ }
793
+ function wrapPreparedStatement(stmt, sql) {
794
+ const handler = {
795
+ get(target, prop) {
796
+ const value = target[prop];
797
+ if (typeof value === "function" && (prop === "all" || prop === "get" || prop === "run")) {
798
+ return function(...args) {
799
+ const collector = getDebugCollector();
800
+ const start = performance.now();
801
+ const result = value.apply(target, args);
802
+ const duration = performance.now() - start;
803
+ if (collector) {
804
+ collector.recordQuery({
805
+ sql,
806
+ params: args,
807
+ duration,
808
+ rows: Array.isArray(result) ? result.length : result ? 1 : 0,
809
+ source: "bun:sqlite"
810
+ });
811
+ }
812
+ return result;
813
+ };
814
+ }
815
+ return value;
816
+ }
817
+ };
818
+ return new Proxy(stmt, handler);
819
+ }
820
+ async function wrapQuery(sql, queryFn, source = "sql") {
821
+ const collector = getDebugCollector();
822
+ const start = performance.now();
823
+ const result = await queryFn();
824
+ const duration = performance.now() - start;
825
+ if (collector) {
826
+ collector.recordQuery({
827
+ sql,
828
+ duration,
829
+ rows: Array.isArray(result) ? result.length : result ? 1 : 0,
830
+ source
831
+ });
832
+ }
833
+ return result;
834
+ }
835
+ function createQueryWrapper(source) {
836
+ return (sql, queryFn) => {
837
+ return wrapQuery(sql, queryFn, source);
838
+ };
839
+ }
571
840
 
572
841
  // src/debug/index.ts
573
842
  async function renderWithDebug(env, templateName, context = {}, options = {}) {
@@ -666,13 +935,21 @@ function debugMiddleware(env, options = {}) {
666
935
  };
667
936
  }
668
937
  export {
938
+ wrapQuery,
939
+ wrapDrizzleQuery,
940
+ wrapBunSQL,
669
941
  startDebugCollection,
942
+ setupPrismaLogging,
670
943
  renderWithDebug,
671
944
  renderStringWithDebug,
945
+ recordQuery,
672
946
  getDebugCollector,
673
947
  generateDebugPanel,
674
948
  endDebugCollection,
675
949
  debugMiddleware,
950
+ createQueryWrapper,
951
+ createPrismaMiddleware,
952
+ createDrizzleLogger,
676
953
  createDebugRenderer,
677
954
  DebugCollector
678
955
  };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * ORM Integrations for Query Telemetry
3
+ *
4
+ * Provides helpers for Prisma, Drizzle, and Bun SQL
5
+ */
6
+ import type { QueryInfo } from './collector';
7
+ type QueryInput = Omit<QueryInfo, 'timestamp' | 'isN1'>;
8
+ /**
9
+ * Record a query manually (works with any database)
10
+ */
11
+ export declare function recordQuery(query: QueryInput): void;
12
+ /**
13
+ * Create Prisma middleware for query telemetry
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { PrismaClient } from '@prisma/client'
18
+ * import { createPrismaMiddleware } from 'binja/debug'
19
+ *
20
+ * const prisma = new PrismaClient()
21
+ * prisma.$use(createPrismaMiddleware())
22
+ * ```
23
+ */
24
+ export declare function createPrismaMiddleware(): (params: any, next: (params: any) => Promise<any>) => Promise<any>;
25
+ /**
26
+ * Setup Prisma query event logging
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { PrismaClient } from '@prisma/client'
31
+ * import { setupPrismaLogging } from 'binja/debug'
32
+ *
33
+ * const prisma = new PrismaClient({ log: [{ emit: 'event', level: 'query' }] })
34
+ * setupPrismaLogging(prisma)
35
+ * ```
36
+ */
37
+ export declare function setupPrismaLogging(prisma: any): void;
38
+ /**
39
+ * Create Drizzle logger for query telemetry
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { drizzle } from 'drizzle-orm/...'
44
+ * import { createDrizzleLogger } from 'binja/debug'
45
+ *
46
+ * const db = drizzle(client, { logger: createDrizzleLogger() })
47
+ * ```
48
+ */
49
+ export declare function createDrizzleLogger(): {
50
+ logQuery(query: string, params: unknown[]): void;
51
+ };
52
+ /**
53
+ * Wrap a Drizzle query for accurate timing
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { wrapDrizzleQuery } from 'binja/debug'
58
+ *
59
+ * const users = await wrapDrizzleQuery(
60
+ * db.select().from(usersTable).where(eq(usersTable.id, 1))
61
+ * )
62
+ * ```
63
+ */
64
+ export declare function wrapDrizzleQuery<T>(query: Promise<T>, sql?: string): Promise<T>;
65
+ /**
66
+ * Wrap Bun SQL database for query telemetry
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import { Database } from 'bun:sqlite'
71
+ * import { wrapBunSQL } from 'binja/debug'
72
+ *
73
+ * const db = wrapBunSQL(new Database('mydb.sqlite'))
74
+ * ```
75
+ */
76
+ export declare function wrapBunSQL<T extends object>(db: T): T;
77
+ /**
78
+ * Wrap any async query function for timing
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * import { wrapQuery } from 'binja/debug'
83
+ *
84
+ * const result = await wrapQuery(
85
+ * 'SELECT * FROM users WHERE id = ?',
86
+ * () => db.query('SELECT * FROM users WHERE id = ?', [1])
87
+ * )
88
+ * ```
89
+ */
90
+ export declare function wrapQuery<T>(sql: string, queryFn: () => Promise<T>, source?: string): Promise<T>;
91
+ /**
92
+ * Create a query wrapper for any database client
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { createQueryWrapper } from 'binja/debug'
97
+ *
98
+ * const query = createQueryWrapper('mysql')
99
+ * const users = await query('SELECT * FROM users', () => mysql.query('SELECT * FROM users'))
100
+ * ```
101
+ */
102
+ export declare function createQueryWrapper(source: string): <T>(sql: string, queryFn: () => Promise<T>) => Promise<T>;
103
+ export {};
104
+ //# sourceMappingURL=integrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../src/debug/integrations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,KAAK,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,CAAC,CAAA;AAEvD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAKnD;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,KACtB,QAAQ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,kBAqB/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAYpD;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB;oBAEf,MAAM,UAAU,OAAO,EAAE,GAAG,IAAI;EAcnD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CA0CrD;AA0CD;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,MAAM,SAAQ,GACb,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,IACvC,CAAC,EAAE,KAAK,MAAM,EAAE,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CAG/D"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Rich Error Formatting for binja
3
+ *
4
+ * Provides detailed error messages with:
5
+ * - Source code context (snippet)
6
+ * - Caret pointer to exact location
7
+ * - "Did you mean?" suggestions
8
+ * - ANSI colors for terminal output
9
+ */
10
+ export interface ErrorLocation {
11
+ line: number;
12
+ column: number;
13
+ source?: string;
14
+ templateName?: string;
15
+ }
16
+ export interface ErrorOptions extends ErrorLocation {
17
+ suggestion?: string;
18
+ availableOptions?: string[];
19
+ }
20
+ /**
21
+ * Base template error with rich formatting
22
+ */
23
+ export declare class TemplateError extends Error {
24
+ line: number;
25
+ column: number;
26
+ source?: string;
27
+ templateName?: string;
28
+ suggestion?: string;
29
+ availableOptions?: string[];
30
+ constructor(message: string, options: ErrorOptions);
31
+ }
32
+ /**
33
+ * Syntax errors (lexer/parser)
34
+ */
35
+ export declare class TemplateSyntaxError extends Error {
36
+ line: number;
37
+ column: number;
38
+ source?: string;
39
+ templateName?: string;
40
+ suggestion?: string;
41
+ constructor(message: string, options: ErrorOptions);
42
+ }
43
+ /**
44
+ * Runtime errors (undefined variables, filter errors)
45
+ */
46
+ export declare class TemplateRuntimeError extends Error {
47
+ line: number;
48
+ column: number;
49
+ source?: string;
50
+ templateName?: string;
51
+ suggestion?: string;
52
+ availableOptions?: string[];
53
+ constructor(message: string, options: ErrorOptions);
54
+ }
55
+ /**
56
+ * Find similar string (for "Did you mean?" suggestions)
57
+ * Uses Levenshtein distance
58
+ */
59
+ export declare function findSimilar(input: string, candidates: string[], maxDistance?: number): string | null;
60
+ /**
61
+ * Helper to create errors with source context
62
+ */
63
+ export declare function createSyntaxError(message: string, line: number, column: number, source?: string, suggestion?: string): TemplateSyntaxError;
64
+ export declare function createRuntimeError(message: string, line: number, column: number, source?: string, suggestion?: string, availableOptions?: string[]): TemplateRuntimeError;
65
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;gBAEtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAWnD;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;gBAEd,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAUnD;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;gBAEtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAWnD;AA4ED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,WAAW,SAAI,GAAG,MAAM,GAAG,IAAI,CAe/F;AAqCD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,mBAAmB,CAErB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,oBAAoB,CAEtB"}
package/dist/index.d.ts CHANGED
@@ -199,6 +199,7 @@ export type { TemplateNode, ASTNode, ExpressionNode } from './parser/nodes';
199
199
  export { Runtime, Context } from './runtime';
200
200
  export { builtinFilters } from './filters';
201
201
  export type { FilterFunction } from './filters';
202
+ export { TemplateError, TemplateSyntaxError, TemplateRuntimeError } from './errors';
202
203
  export type { CompileOptions } from './compiler';
203
204
  export { builtinTests } from './tests';
204
205
  export type { TestFunction } from './tests';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}