@pineliner/odb-client 1.0.3 → 1.0.4

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.
@@ -7,7 +7,7 @@ export interface SQLParserOptions {
7
7
  }
8
8
  /**
9
9
  * Parse SQL file into statements, separating PRAGMA from regular SQL
10
- * Uses node-sql-parser for robust SQL parsing
10
+ * Uses custom parser that handles BEGIN...END blocks
11
11
  */
12
12
  export declare function parseSQL(sqlContent: string, options?: SQLParserOptions): ParsedStatements;
13
13
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sql-parser.d.ts","sourceRoot":"","sources":["../../src/database/sql-parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,gBAAgB,CA0B7F;AAwHD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/D"}
1
+ {"version":3,"file":"sql-parser.d.ts","sourceRoot":"","sources":["../../src/database/sql-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,gBAAgB,CA0B7F;AAoFD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/D"}
package/dist/index.cjs CHANGED
@@ -1441,14 +1441,13 @@ const external_libsql_client_namespaceObject = require("@libsql/client");
1441
1441
  // No explicit close needed
1442
1442
  }
1443
1443
  }
1444
- const external_node_sql_parser_namespaceObject = require("node-sql-parser");
1445
1444
  /**
1446
1445
  * Parse SQL file into statements, separating PRAGMA from regular SQL
1447
- * Uses node-sql-parser for robust SQL parsing
1446
+ * Uses custom parser that handles BEGIN...END blocks
1448
1447
  */ function parseSQL(sqlContent, options = {}) {
1449
1448
  const separatePragma = options.separatePragma ?? true;
1450
- // Use node-sql-parser to properly split SQL statements
1451
- const statements = splitStatementsWithParser(sqlContent);
1449
+ // Split SQL statements manually
1450
+ const statements = splitStatements(sqlContent);
1452
1451
  if (!separatePragma) return {
1453
1452
  pragmaStatements: [],
1454
1453
  regularStatements: statements
@@ -1465,54 +1464,29 @@ const external_node_sql_parser_namespaceObject = require("node-sql-parser");
1465
1464
  regularStatements
1466
1465
  };
1467
1466
  }
1468
- /**
1469
- * Split SQL content using node-sql-parser (more robust than custom parser)
1470
- * Falls back to simple split if parser fails
1471
- */ function splitStatementsWithParser(sqlContent) {
1472
- try {
1473
- const parser = new external_node_sql_parser_namespaceObject.Parser();
1474
- // node-sql-parser supports splitting multiple statements
1475
- // Try to use it, but have fallback for edge cases
1476
- const opt = {
1477
- database: 'sqlite',
1478
- type: 'table'
1479
- };
1480
- // Split by semicolons first to handle parser limitations with very large files
1481
- const roughStatements = sqlContent.split(/;[\s\n]*/).map((s)=>s.trim()).filter((s)=>s.length > 0);
1482
- const validStatements = [];
1483
- for (const stmt of roughStatements){
1484
- // Add semicolon back
1485
- const fullStmt = stmt + ';';
1486
- // Skip comments-only statements
1487
- if (!stmt.trim().startsWith('--') && '' !== stmt.trim()) // Validate with parser (but don't fail if it can't parse complex statements)
1488
- try {
1489
- parser.astify(fullStmt, opt);
1490
- validStatements.push(fullStmt);
1491
- } catch (parseError) {
1492
- // If parser can't handle it, include it anyway if it looks like valid SQL
1493
- // This handles complex statements like CREATE TRIGGER, CREATE VIEW with subqueries
1494
- if (stmt.match(/^(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|SELECT|PRAGMA)/i)) validStatements.push(fullStmt);
1495
- else console.warn(`Skipping potentially invalid statement: ${stmt.substring(0, 50)}...`);
1496
- }
1497
- }
1498
- return validStatements;
1499
- } catch (error) {
1500
- console.warn('node-sql-parser failed, using fallback parser:', error);
1501
- // Fallback to original simple parser
1502
- return splitStatements(sqlContent);
1503
- }
1504
- }
1505
1467
  /**
1506
1468
  * Split SQL content into individual statements
1507
- * Handles comments, quotes, and semicolons properly
1469
+ * Handles comments, quotes, semicolons, and BEGIN...END blocks properly
1508
1470
  */ function splitStatements(sqlContent) {
1509
1471
  const statements = [];
1510
1472
  let currentStatement = '';
1511
1473
  let inQuote = false;
1512
1474
  let quoteChar = '';
1475
+ let beginEndDepth = 0;
1513
1476
  const lines = sqlContent.split('\n');
1514
1477
  for (const line of lines){
1515
1478
  let processedLine = '';
1479
+ const lineWithoutComments = line.replace(/--.*$/, '');
1480
+ // Track BEGIN...END depth for this line BEFORE processing characters
1481
+ if (!inQuote && lineWithoutComments.trim()) {
1482
+ const beginMatches = lineWithoutComments.match(/\bBEGIN\b/gi);
1483
+ const endMatches = lineWithoutComments.match(/\bEND\b/gi);
1484
+ if (beginMatches) beginEndDepth += beginMatches.length;
1485
+ if (endMatches) {
1486
+ beginEndDepth -= endMatches.length;
1487
+ if (beginEndDepth < 0) beginEndDepth = 0;
1488
+ }
1489
+ }
1516
1490
  for(let i = 0; i < line.length; i++){
1517
1491
  const char = line[i];
1518
1492
  const prevChar = i > 0 ? line[i - 1] : '';
@@ -1532,11 +1506,11 @@ const external_node_sql_parser_namespaceObject = require("node-sql-parser");
1532
1506
  }
1533
1507
  }
1534
1508
  processedLine += char;
1535
- // Split on semicolon when not in quotes
1536
- if (';' === char && !inQuote) {
1509
+ // Split on semicolon when not in quotes AND not inside BEGIN...END
1510
+ if (';' === char && !inQuote && 0 === beginEndDepth) {
1537
1511
  currentStatement += processedLine;
1538
1512
  const stmt = currentStatement.trim();
1539
- if (stmt) statements.push(stmt);
1513
+ if (stmt && !stmt.startsWith('--')) statements.push(stmt);
1540
1514
  currentStatement = '';
1541
1515
  processedLine = '';
1542
1516
  }
@@ -1545,7 +1519,7 @@ const external_node_sql_parser_namespaceObject = require("node-sql-parser");
1545
1519
  }
1546
1520
  // Handle remaining statement
1547
1521
  const finalStmt = currentStatement.trim();
1548
- if (finalStmt) statements.push(finalStmt);
1522
+ if (finalStmt && !finalStmt.startsWith('--')) statements.push(finalStmt);
1549
1523
  return statements;
1550
1524
  }
1551
1525
  /**
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as __WEBPACK_EXTERNAL_MODULE_bun_sqlite__ from "bun:sqlite";
2
2
  import * as __WEBPACK_EXTERNAL_MODULE__libsql_client__ from "@libsql/client";
3
- import * as __WEBPACK_EXTERNAL_MODULE_node_sql_parser__ from "node-sql-parser";
4
3
  import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
5
4
  // Core types for the ODBLite client
6
5
  // Error types
@@ -1369,11 +1368,11 @@ ODBLiteClient.join;
1369
1368
  }
1370
1369
  /**
1371
1370
  * Parse SQL file into statements, separating PRAGMA from regular SQL
1372
- * Uses node-sql-parser for robust SQL parsing
1371
+ * Uses custom parser that handles BEGIN...END blocks
1373
1372
  */ function parseSQL(sqlContent, options = {}) {
1374
1373
  const separatePragma = options.separatePragma ?? true;
1375
- // Use node-sql-parser to properly split SQL statements
1376
- const statements = splitStatementsWithParser(sqlContent);
1374
+ // Split SQL statements manually
1375
+ const statements = splitStatements(sqlContent);
1377
1376
  if (!separatePragma) return {
1378
1377
  pragmaStatements: [],
1379
1378
  regularStatements: statements
@@ -1390,54 +1389,29 @@ ODBLiteClient.join;
1390
1389
  regularStatements
1391
1390
  };
1392
1391
  }
1393
- /**
1394
- * Split SQL content using node-sql-parser (more robust than custom parser)
1395
- * Falls back to simple split if parser fails
1396
- */ function splitStatementsWithParser(sqlContent) {
1397
- try {
1398
- const parser = new __WEBPACK_EXTERNAL_MODULE_node_sql_parser__.Parser();
1399
- // node-sql-parser supports splitting multiple statements
1400
- // Try to use it, but have fallback for edge cases
1401
- const opt = {
1402
- database: 'sqlite',
1403
- type: 'table'
1404
- };
1405
- // Split by semicolons first to handle parser limitations with very large files
1406
- const roughStatements = sqlContent.split(/;[\s\n]*/).map((s)=>s.trim()).filter((s)=>s.length > 0);
1407
- const validStatements = [];
1408
- for (const stmt of roughStatements){
1409
- // Add semicolon back
1410
- const fullStmt = stmt + ';';
1411
- // Skip comments-only statements
1412
- if (!stmt.trim().startsWith('--') && '' !== stmt.trim()) // Validate with parser (but don't fail if it can't parse complex statements)
1413
- try {
1414
- parser.astify(fullStmt, opt);
1415
- validStatements.push(fullStmt);
1416
- } catch (parseError) {
1417
- // If parser can't handle it, include it anyway if it looks like valid SQL
1418
- // This handles complex statements like CREATE TRIGGER, CREATE VIEW with subqueries
1419
- if (stmt.match(/^(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|SELECT|PRAGMA)/i)) validStatements.push(fullStmt);
1420
- else console.warn(`Skipping potentially invalid statement: ${stmt.substring(0, 50)}...`);
1421
- }
1422
- }
1423
- return validStatements;
1424
- } catch (error) {
1425
- console.warn('node-sql-parser failed, using fallback parser:', error);
1426
- // Fallback to original simple parser
1427
- return splitStatements(sqlContent);
1428
- }
1429
- }
1430
1392
  /**
1431
1393
  * Split SQL content into individual statements
1432
- * Handles comments, quotes, and semicolons properly
1394
+ * Handles comments, quotes, semicolons, and BEGIN...END blocks properly
1433
1395
  */ function splitStatements(sqlContent) {
1434
1396
  const statements = [];
1435
1397
  let currentStatement = '';
1436
1398
  let inQuote = false;
1437
1399
  let quoteChar = '';
1400
+ let beginEndDepth = 0;
1438
1401
  const lines = sqlContent.split('\n');
1439
1402
  for (const line of lines){
1440
1403
  let processedLine = '';
1404
+ const lineWithoutComments = line.replace(/--.*$/, '');
1405
+ // Track BEGIN...END depth for this line BEFORE processing characters
1406
+ if (!inQuote && lineWithoutComments.trim()) {
1407
+ const beginMatches = lineWithoutComments.match(/\bBEGIN\b/gi);
1408
+ const endMatches = lineWithoutComments.match(/\bEND\b/gi);
1409
+ if (beginMatches) beginEndDepth += beginMatches.length;
1410
+ if (endMatches) {
1411
+ beginEndDepth -= endMatches.length;
1412
+ if (beginEndDepth < 0) beginEndDepth = 0;
1413
+ }
1414
+ }
1441
1415
  for(let i = 0; i < line.length; i++){
1442
1416
  const char = line[i];
1443
1417
  const prevChar = i > 0 ? line[i - 1] : '';
@@ -1457,11 +1431,11 @@ ODBLiteClient.join;
1457
1431
  }
1458
1432
  }
1459
1433
  processedLine += char;
1460
- // Split on semicolon when not in quotes
1461
- if (';' === char && !inQuote) {
1434
+ // Split on semicolon when not in quotes AND not inside BEGIN...END
1435
+ if (';' === char && !inQuote && 0 === beginEndDepth) {
1462
1436
  currentStatement += processedLine;
1463
1437
  const stmt = currentStatement.trim();
1464
- if (stmt) statements.push(stmt);
1438
+ if (stmt && !stmt.startsWith('--')) statements.push(stmt);
1465
1439
  currentStatement = '';
1466
1440
  processedLine = '';
1467
1441
  }
@@ -1470,7 +1444,7 @@ ODBLiteClient.join;
1470
1444
  }
1471
1445
  // Handle remaining statement
1472
1446
  const finalStmt = currentStatement.trim();
1473
- if (finalStmt) statements.push(finalStmt);
1447
+ if (finalStmt && !finalStmt.startsWith('--')) statements.push(finalStmt);
1474
1448
  return statements;
1475
1449
  }
1476
1450
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pineliner/odb-client",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Isomorphic client for ODB-Lite with postgres.js-like template string SQL support",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -1,5 +1,3 @@
1
- import { Parser } from 'node-sql-parser'
2
-
3
1
  export interface ParsedStatements {
4
2
  pragmaStatements: string[]
5
3
  regularStatements: string[]
@@ -11,13 +9,13 @@ export interface SQLParserOptions {
11
9
 
12
10
  /**
13
11
  * Parse SQL file into statements, separating PRAGMA from regular SQL
14
- * Uses node-sql-parser for robust SQL parsing
12
+ * Uses custom parser that handles BEGIN...END blocks
15
13
  */
16
14
  export function parseSQL(sqlContent: string, options: SQLParserOptions = {}): ParsedStatements {
17
15
  const separatePragma = options.separatePragma ?? true
18
16
 
19
- // Use node-sql-parser to properly split SQL statements
20
- const statements = splitStatementsWithParser(sqlContent)
17
+ // Split SQL statements manually
18
+ const statements = splitStatements(sqlContent)
21
19
 
22
20
  if (!separatePragma) {
23
21
  return {
@@ -41,74 +39,38 @@ export function parseSQL(sqlContent: string, options: SQLParserOptions = {}): Pa
41
39
  return { pragmaStatements, regularStatements }
42
40
  }
43
41
 
44
- /**
45
- * Split SQL content using node-sql-parser (more robust than custom parser)
46
- * Falls back to simple split if parser fails
47
- */
48
- function splitStatementsWithParser(sqlContent: string): string[] {
49
- try {
50
- const parser = new Parser()
51
-
52
- // node-sql-parser supports splitting multiple statements
53
- // Try to use it, but have fallback for edge cases
54
- const opt = {
55
- database: 'sqlite',
56
- type: 'table' as any
57
- }
58
-
59
- // Split by semicolons first to handle parser limitations with very large files
60
- const roughStatements = sqlContent.split(/;[\s\n]*/)
61
- .map(s => s.trim())
62
- .filter(s => s.length > 0)
63
-
64
- const validStatements: string[] = []
65
-
66
- for (const stmt of roughStatements) {
67
- // Add semicolon back
68
- const fullStmt = stmt + ';'
69
-
70
- // Skip comments-only statements
71
- if (stmt.trim().startsWith('--') || stmt.trim() === '') {
72
- continue
73
- }
74
-
75
- // Validate with parser (but don't fail if it can't parse complex statements)
76
- try {
77
- parser.astify(fullStmt, opt)
78
- validStatements.push(fullStmt)
79
- } catch (parseError) {
80
- // If parser can't handle it, include it anyway if it looks like valid SQL
81
- // This handles complex statements like CREATE TRIGGER, CREATE VIEW with subqueries
82
- if (stmt.match(/^(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|SELECT|PRAGMA)/i)) {
83
- validStatements.push(fullStmt)
84
- } else {
85
- console.warn(`Skipping potentially invalid statement: ${stmt.substring(0, 50)}...`)
86
- }
87
- }
88
- }
89
-
90
- return validStatements
91
- } catch (error) {
92
- console.warn('node-sql-parser failed, using fallback parser:', error)
93
- // Fallback to original simple parser
94
- return splitStatements(sqlContent)
95
- }
96
- }
97
-
98
42
  /**
99
43
  * Split SQL content into individual statements
100
- * Handles comments, quotes, and semicolons properly
44
+ * Handles comments, quotes, semicolons, and BEGIN...END blocks properly
101
45
  */
102
46
  function splitStatements(sqlContent: string): string[] {
103
47
  const statements: string[] = []
104
48
  let currentStatement = ''
105
49
  let inQuote = false
106
50
  let quoteChar = ''
51
+ let beginEndDepth = 0
107
52
 
108
53
  const lines = sqlContent.split('\n')
109
54
 
110
55
  for (const line of lines) {
111
56
  let processedLine = ''
57
+ const lineWithoutComments = line.replace(/--.*$/, '')
58
+
59
+ // Track BEGIN...END depth for this line BEFORE processing characters
60
+ if (!inQuote && lineWithoutComments.trim()) {
61
+ const beginMatches = lineWithoutComments.match(/\bBEGIN\b/gi)
62
+ const endMatches = lineWithoutComments.match(/\bEND\b/gi)
63
+
64
+ if (beginMatches) {
65
+ beginEndDepth += beginMatches.length
66
+ }
67
+ if (endMatches) {
68
+ beginEndDepth -= endMatches.length
69
+ if (beginEndDepth < 0) {
70
+ beginEndDepth = 0
71
+ }
72
+ }
73
+ }
112
74
 
113
75
  for (let i = 0; i < line.length; i++) {
114
76
  const char = line[i]
@@ -133,11 +95,11 @@ function splitStatements(sqlContent: string): string[] {
133
95
 
134
96
  processedLine += char
135
97
 
136
- // Split on semicolon when not in quotes
137
- if (char === ';' && !inQuote) {
98
+ // Split on semicolon when not in quotes AND not inside BEGIN...END
99
+ if (char === ';' && !inQuote && beginEndDepth === 0) {
138
100
  currentStatement += processedLine
139
101
  const stmt = currentStatement.trim()
140
- if (stmt) {
102
+ if (stmt && !stmt.startsWith('--')) {
141
103
  statements.push(stmt)
142
104
  }
143
105
  currentStatement = ''
@@ -152,7 +114,7 @@ function splitStatements(sqlContent: string): string[] {
152
114
 
153
115
  // Handle remaining statement
154
116
  const finalStmt = currentStatement.trim()
155
- if (finalStmt) {
117
+ if (finalStmt && !finalStmt.startsWith('--')) {
156
118
  statements.push(finalStmt)
157
119
  }
158
120