@514labs/moose-lsp 1.4.0 → 1.4.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.
- package/dist/codeActions.d.ts +7 -2
- package/dist/codeActions.js +57 -10
- package/dist/codeActions.js.map +1 -1
- package/dist/codeActions.test.js +64 -2
- package/dist/codeActions.test.js.map +1 -1
- package/dist/diagnostics.d.ts +9 -1
- package/dist/diagnostics.js +24 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/diagnostics.test.js +56 -5
- package/dist/diagnostics.test.js.map +1 -1
- package/dist/node_modules/@514labs/moose-sql-validator-wasm/package.json +1 -1
- package/dist/node_modules/@514labs/moose-sql-validator-wasm/pkg/sql_validator_bg.wasm +0 -0
- package/dist/pythonSqlExtractor.js +5 -1
- package/dist/pythonSqlExtractor.js.map +1 -1
- package/dist/server.integration.test.js +222 -26
- package/dist/server.integration.test.js.map +1 -1
- package/dist/server.js +209 -87
- package/dist/server.js.map +1 -1
- package/dist/serverLogic.js +9 -0
- package/dist/serverLogic.js.map +1 -1
- package/dist/serverLogic.test.js +127 -10
- package/dist/serverLogic.test.js.map +1 -1
- package/dist/sqlExtractor.js +43 -12
- package/dist/sqlExtractor.js.map +1 -1
- package/dist/sqlExtractor.test.js +106 -4
- package/dist/sqlExtractor.test.js.map +1 -1
- package/dist/sqlLocations.d.ts +9 -1
- package/dist/sqlLocations.js +9 -1
- package/dist/sqlLocations.js.map +1 -1
- package/dist/sqlLocations.test.js +49 -1
- package/dist/sqlLocations.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sqlExtractor.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { describe, it } from 'node:test';\nimport ts from 'typescript';\nimport { extractAllSqlLocations, extractSqlLocations } from './sqlExtractor';\n\n/**\n * Creates a TypeScript program from source code strings for testing.\n * Simulates moose-lib by providing a mock sql function declaration.\n */\nfunction createTestProgram(files: Record<string, string>): {\n program: ts.Program;\n tmpDir: string;\n} {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sql-extractor-test-'));\n\n // Create a mock moose-lib module with sql function\n const mooseLibDir = path.join(\n tmpDir,\n 'node_modules',\n '@514labs',\n 'moose-lib',\n );\n fs.mkdirSync(mooseLibDir, { recursive: true });\n fs.writeFileSync(\n path.join(mooseLibDir, 'index.d.ts'),\n `export declare function sql(strings: TemplateStringsArray, ...values: any[]): string;`,\n );\n fs.writeFileSync(\n path.join(mooseLibDir, 'index.js'),\n `module.exports.sql = function sql(strings, ...values) { return strings.join(''); };`,\n );\n fs.writeFileSync(\n path.join(mooseLibDir, 'package.json'),\n JSON.stringify({\n name: '@514labs/moose-lib',\n main: 'index.js',\n types: 'index.d.ts',\n }),\n );\n\n // Write test files\n for (const [fileName, content] of Object.entries(files)) {\n const filePath = path.join(tmpDir, fileName);\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n\n // Create tsconfig\n const tsconfigPath = path.join(tmpDir, 'tsconfig.json');\n fs.writeFileSync(\n tsconfigPath,\n JSON.stringify({\n compilerOptions: {\n target: 'ES2020',\n module: 'commonjs',\n strict: true,\n esModuleInterop: true,\n moduleResolution: 'node',\n baseUrl: '.',\n paths: {\n '@514labs/moose-lib': ['node_modules/@514labs/moose-lib'],\n },\n },\n include: ['src/**/*'],\n }),\n );\n\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n tmpDir,\n );\n\n const program = ts.createProgram({\n rootNames: parsed.fileNames,\n options: parsed.options,\n });\n\n return { program, tmpDir };\n}\n\nfunction cleanupTestProject(dir: string): void {\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\ndescribe('sqlExtractor', () => {\n describe('extractSqlLocations', () => {\n it('extracts sql template from file with moose-lib import', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile, 'Source file should exist');\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].templateText, 'SELECT * FROM users');\n assert.strictEqual(locations[0].line, 4);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts multiple sql templates from same file', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query1 = sql\\`SELECT * FROM users\\`;\nconst query2 = sql\\`SELECT * FROM orders\\`;\nconst query3 = sql\\`SELECT * FROM products\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 3);\n assert.strictEqual(locations[0].templateText, 'SELECT * FROM users');\n assert.strictEqual(locations[1].templateText, 'SELECT * FROM orders');\n assert.strictEqual(locations[2].templateText, 'SELECT * FROM products');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('handles template with substitutions', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst tableName = 'users';\nconst column = 'id';\nconst query = sql\\`SELECT \\${column} FROM \\${tableName} WHERE active = \\${true}\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n // Substitutions should be replaced with ${...}\n assert.strictEqual(\n locations[0].templateText,\n 'SELECT ${...} FROM ${...} WHERE active = ${...}',\n );\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('returns empty array for file without sql templates', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nconst x = 1;\nconst y = 2;\nconsole.log(x + y);\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 0);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts sql tag even when symbol cannot be resolved (fallback behavior)', () => {\n // When TypeScript can't resolve the sql symbol (e.g., mock setup issues),\n // we fall back to accepting it (better to have false positives than miss real sql queries)\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\n// Define our own sql function (not from moose-lib)\nfunction sql(strings: TemplateStringsArray, ...values: any[]) {\n return strings.join('');\n}\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n // With fallback behavior, we accept sql tags even when we can't verify\n // they come from moose-lib (better to have false positives)\n assert.strictEqual(locations.length, 1);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts correct line and column positions', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `import { sql } from '@514labs/moose-lib';\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].line, 3);\n // Column should point to the start of the template literal\n assert.ok(locations[0].column > 0);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n });\n\n describe('extractAllSqlLocations', () => {\n it('extracts sql from multiple source files', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/queries/users.ts': `\nimport { sql } from '@514labs/moose-lib';\nexport const getUsersQuery = sql\\`SELECT * FROM users\\`;\n`,\n 'src/queries/orders.ts': `\nimport { sql } from '@514labs/moose-lib';\nexport const getOrdersQuery = sql\\`SELECT * FROM orders\\`;\n`,\n 'src/index.ts': `\nexport * from './queries/users';\nexport * from './queries/orders';\n`,\n });\n\n try {\n const typeChecker = program.getTypeChecker();\n const sourceFiles = program\n .getSourceFiles()\n .filter(\n (sf) =>\n !sf.isDeclarationFile && !sf.fileName.includes('node_modules'),\n );\n\n const locations = extractAllSqlLocations(sourceFiles, typeChecker);\n\n assert.strictEqual(locations.length, 2);\n\n const templates = locations.map((l) => l.templateText);\n assert.ok(templates.includes('SELECT * FROM users'));\n assert.ok(templates.includes('SELECT * FROM orders'));\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n });\n});\n"],"mappings":"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","names":["ts","assert"]}
|
|
1
|
+
{"version":3,"sources":["../src/sqlExtractor.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { describe, it } from 'node:test';\nimport ts from 'typescript';\nimport { extractAllSqlLocations, extractSqlLocations } from './sqlExtractor';\n\n/**\n * Creates a TypeScript program from source code strings for testing.\n * Simulates moose-lib by providing a mock sql function declaration.\n */\nfunction createTestProgram(files: Record<string, string>): {\n program: ts.Program;\n tmpDir: string;\n} {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sql-extractor-test-'));\n\n // Create a mock moose-lib module with sql function\n const mooseLibDir = path.join(\n tmpDir,\n 'node_modules',\n '@514labs',\n 'moose-lib',\n );\n fs.mkdirSync(mooseLibDir, { recursive: true });\n fs.writeFileSync(\n path.join(mooseLibDir, 'index.d.ts'),\n `\ninterface SqlTemplateTag {\n (strings: TemplateStringsArray, ...values: any[]): string;\n statement(strings: TemplateStringsArray, ...values: any[]): string;\n fragment(strings: TemplateStringsArray, ...values: any[]): string;\n}\nexport declare const sql: SqlTemplateTag;\n`,\n );\n fs.writeFileSync(\n path.join(mooseLibDir, 'index.js'),\n `\nconst handler = function(strings, ...values) { return strings.join(''); };\nhandler.statement = handler;\nhandler.fragment = handler;\nmodule.exports.sql = handler;\n`,\n );\n fs.writeFileSync(\n path.join(mooseLibDir, 'package.json'),\n JSON.stringify({\n name: '@514labs/moose-lib',\n main: 'index.js',\n types: 'index.d.ts',\n }),\n );\n\n // Write test files\n for (const [fileName, content] of Object.entries(files)) {\n const filePath = path.join(tmpDir, fileName);\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(filePath, content);\n }\n\n // Create tsconfig\n const tsconfigPath = path.join(tmpDir, 'tsconfig.json');\n fs.writeFileSync(\n tsconfigPath,\n JSON.stringify({\n compilerOptions: {\n target: 'ES2020',\n module: 'commonjs',\n strict: true,\n esModuleInterop: true,\n moduleResolution: 'node',\n baseUrl: '.',\n paths: {\n '@514labs/moose-lib': ['node_modules/@514labs/moose-lib'],\n },\n },\n include: ['src/**/*'],\n }),\n );\n\n const configFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n const parsed = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n tmpDir,\n );\n\n const program = ts.createProgram({\n rootNames: parsed.fileNames,\n options: parsed.options,\n });\n\n return { program, tmpDir };\n}\n\nfunction cleanupTestProject(dir: string): void {\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\ndescribe('sqlExtractor', () => {\n describe('extractSqlLocations', () => {\n it('extracts sql template from file with moose-lib import', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile, 'Source file should exist');\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].templateText, 'SELECT * FROM users');\n assert.strictEqual(locations[0].line, 4);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts multiple sql templates from same file', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query1 = sql\\`SELECT * FROM users\\`;\nconst query2 = sql\\`SELECT * FROM orders\\`;\nconst query3 = sql\\`SELECT * FROM products\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 3);\n assert.strictEqual(locations[0].templateText, 'SELECT * FROM users');\n assert.strictEqual(locations[1].templateText, 'SELECT * FROM orders');\n assert.strictEqual(locations[2].templateText, 'SELECT * FROM products');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('handles template with substitutions', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst tableName = 'users';\nconst column = 'id';\nconst query = sql\\`SELECT \\${column} FROM \\${tableName} WHERE active = \\${true}\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n // Substitutions should be replaced with ${...}\n assert.strictEqual(\n locations[0].templateText,\n 'SELECT ${...} FROM ${...} WHERE active = ${...}',\n );\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('returns empty array for file without sql templates', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nconst x = 1;\nconst y = 2;\nconsole.log(x + y);\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 0);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('ignores sql tag when symbol resolves to non-moose-lib declaration', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\n// Define our own sql function (not from moose-lib)\nfunction sql(strings: TemplateStringsArray, ...values: any[]) {\n return strings.join('');\n}\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n // Symbol resolves to a local function, not moose-lib — should be ignored\n assert.strictEqual(locations.length, 0);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts correct line and column positions', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `import { sql } from '@514labs/moose-lib';\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].line, 3);\n // Column should point to the start of the template literal\n assert.ok(locations[0].column > 0);\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n it('extracts sql.statement with tagKind \"statement\"', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query = sql.statement\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].templateText, 'SELECT * FROM users');\n assert.strictEqual(locations[0].tagKind, 'statement');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts sql.fragment with tagKind \"fragment\"', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst condition = sql.fragment\\`status = 'active'\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].templateText, \"status = 'active'\");\n assert.strictEqual(locations[0].tagKind, 'fragment');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts bare sql with tagKind \"bare\"', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst query = sql\\`SELECT * FROM users\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 1);\n assert.strictEqual(locations[0].tagKind, 'bare');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n\n it('extracts mixed tag kinds from same file', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/index.ts': `\nimport { sql } from '@514labs/moose-lib';\n\nconst a = sql\\`SELECT 1\\`;\nconst b = sql.statement\\`SELECT 2\\`;\nconst c = sql.fragment\\`col = 1\\`;\n`,\n });\n\n try {\n const sourceFile = program.getSourceFile(\n path.join(tmpDir, 'src/index.ts'),\n );\n assert.ok(sourceFile);\n\n const typeChecker = program.getTypeChecker();\n const locations = extractSqlLocations(sourceFile, typeChecker);\n\n assert.strictEqual(locations.length, 3);\n assert.strictEqual(locations[0].tagKind, 'bare');\n assert.strictEqual(locations[1].tagKind, 'statement');\n assert.strictEqual(locations[2].tagKind, 'fragment');\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n });\n\n describe('extractAllSqlLocations', () => {\n it('extracts sql from multiple source files', () => {\n const { program, tmpDir } = createTestProgram({\n 'src/queries/users.ts': `\nimport { sql } from '@514labs/moose-lib';\nexport const getUsersQuery = sql\\`SELECT * FROM users\\`;\n`,\n 'src/queries/orders.ts': `\nimport { sql } from '@514labs/moose-lib';\nexport const getOrdersQuery = sql\\`SELECT * FROM orders\\`;\n`,\n 'src/index.ts': `\nexport * from './queries/users';\nexport * from './queries/orders';\n`,\n });\n\n try {\n const typeChecker = program.getTypeChecker();\n const sourceFiles = program\n .getSourceFiles()\n .filter(\n (sf) =>\n !sf.isDeclarationFile && !sf.fileName.includes('node_modules'),\n );\n\n const locations = extractAllSqlLocations(sourceFiles, typeChecker);\n\n assert.strictEqual(locations.length, 2);\n\n const templates = locations.map((l) => l.templateText);\n assert.ok(templates.includes('SELECT * FROM users'));\n assert.ok(templates.includes('SELECT * FROM orders'));\n } finally {\n cleanupTestProject(tmpDir);\n }\n });\n });\n});\n"],"mappings":"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","names":["ts","assert"]}
|
package/dist/sqlLocations.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
type SqlTagKind = 'statement' | 'fragment' | 'bare';
|
|
1
2
|
/**
|
|
2
3
|
* Represents a SQL template literal location from .moose/sql-locations.json
|
|
3
4
|
*/
|
|
@@ -9,6 +10,13 @@ interface SqlLocation {
|
|
|
9
10
|
endLine: number;
|
|
10
11
|
endColumn: number;
|
|
11
12
|
templateText: string;
|
|
13
|
+
tagKind: SqlTagKind;
|
|
14
|
+
/** 1-indexed line of the tag identifier (e.g., `sql` or `sql.statement`) */
|
|
15
|
+
tagLine: number;
|
|
16
|
+
/** 1-indexed column of the tag identifier start */
|
|
17
|
+
tagColumn: number;
|
|
18
|
+
/** 1-indexed column of the tag identifier end */
|
|
19
|
+
tagEndColumn: number;
|
|
12
20
|
}
|
|
13
21
|
/**
|
|
14
22
|
* The manifest format for .moose/sql-locations.json
|
|
@@ -28,4 +36,4 @@ declare function loadSqlLocations(jsonContent: string): SqlLocationManifest;
|
|
|
28
36
|
*/
|
|
29
37
|
declare function prepareSqlForValidation(templateText: string): string;
|
|
30
38
|
|
|
31
|
-
export { type SqlLocation, type SqlLocationManifest, loadSqlLocations, prepareSqlForValidation };
|
|
39
|
+
export { type SqlLocation, type SqlLocationManifest, type SqlTagKind, loadSqlLocations, prepareSqlForValidation };
|
package/dist/sqlLocations.js
CHANGED
|
@@ -27,7 +27,15 @@ function loadSqlLocations(jsonContent) {
|
|
|
27
27
|
const parsed = JSON.parse(jsonContent);
|
|
28
28
|
return {
|
|
29
29
|
version: parsed.version ?? 1,
|
|
30
|
-
sqlLocations: Array.isArray(parsed.sqlLocations) ? parsed.sqlLocations
|
|
30
|
+
sqlLocations: Array.isArray(parsed.sqlLocations) ? parsed.sqlLocations.map(
|
|
31
|
+
(loc) => ({
|
|
32
|
+
...loc,
|
|
33
|
+
tagKind: loc.tagKind ?? "statement",
|
|
34
|
+
tagLine: loc.tagLine ?? loc.line ?? 1,
|
|
35
|
+
tagColumn: loc.tagColumn ?? loc.column ?? 1,
|
|
36
|
+
tagEndColumn: loc.tagEndColumn ?? loc.column ?? 1
|
|
37
|
+
})
|
|
38
|
+
) : []
|
|
31
39
|
};
|
|
32
40
|
} catch {
|
|
33
41
|
return {
|
package/dist/sqlLocations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sqlLocations.ts"],"sourcesContent":["/**\n * Represents a SQL template literal location from .moose/sql-locations.json\n */\nexport interface SqlLocation {\n id: string;\n file: string;\n line: number;\n column: number;\n endLine: number;\n endColumn: number;\n templateText: string;\n}\n\n/**\n * The manifest format for .moose/sql-locations.json\n */\nexport interface SqlLocationManifest {\n version: number;\n sqlLocations: SqlLocation[];\n}\n\n/**\n * Parses sql-locations.json content and returns the manifest.\n * Returns empty locations on parse error (graceful degradation).\n */\nexport function loadSqlLocations(jsonContent: string): SqlLocationManifest {\n try {\n const parsed = JSON.parse(jsonContent);\n return {\n version: parsed.version ?? 1,\n sqlLocations: Array.isArray(parsed.sqlLocations)\n ? parsed.sqlLocations\n : [],\n };\n } catch {\n // Graceful degradation - return empty manifest on parse error\n return {\n version: 1,\n sqlLocations: [],\n };\n }\n}\n\n/**\n * Prepares template text for SQL validation by replacing ${...} placeholders\n * with valid SQL identifiers that won't cause parse errors.\n */\nexport function prepareSqlForValidation(templateText: string): string {\n // Replace ${...} with a placeholder identifier that's valid in SQL\n // Using '_ph_N' pattern to create unique, valid identifiers\n let counter = 0;\n return templateText.replace(/\\$\\{\\.\\.\\.\\}/g, () => {\n counter++;\n return `_ph_${counter}`;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../src/sqlLocations.ts"],"sourcesContent":["export type SqlTagKind = 'statement' | 'fragment' | 'bare';\n\n/**\n * Represents a SQL template literal location from .moose/sql-locations.json\n */\nexport interface SqlLocation {\n id: string;\n file: string;\n line: number;\n column: number;\n endLine: number;\n endColumn: number;\n templateText: string;\n tagKind: SqlTagKind;\n /** 1-indexed line of the tag identifier (e.g., `sql` or `sql.statement`) */\n tagLine: number;\n /** 1-indexed column of the tag identifier start */\n tagColumn: number;\n /** 1-indexed column of the tag identifier end */\n tagEndColumn: number;\n}\n\n/**\n * The manifest format for .moose/sql-locations.json\n */\nexport interface SqlLocationManifest {\n version: number;\n sqlLocations: SqlLocation[];\n}\n\n/**\n * Parses sql-locations.json content and returns the manifest.\n * Returns empty locations on parse error (graceful degradation).\n */\nexport function loadSqlLocations(jsonContent: string): SqlLocationManifest {\n try {\n const parsed = JSON.parse(jsonContent);\n return {\n version: parsed.version ?? 1,\n sqlLocations: Array.isArray(parsed.sqlLocations)\n ? parsed.sqlLocations.map(\n (loc: Record<string, unknown>): SqlLocation => ({\n ...(loc as unknown as SqlLocation),\n tagKind: (loc.tagKind as SqlTagKind | undefined) ?? 'statement',\n tagLine:\n (loc.tagLine as number | undefined) ??\n (loc.line as number) ??\n 1,\n tagColumn:\n (loc.tagColumn as number | undefined) ??\n (loc.column as number) ??\n 1,\n tagEndColumn:\n (loc.tagEndColumn as number | undefined) ??\n (loc.column as number) ??\n 1,\n }),\n )\n : [],\n };\n } catch {\n // Graceful degradation - return empty manifest on parse error\n return {\n version: 1,\n sqlLocations: [],\n };\n }\n}\n\n/**\n * Prepares template text for SQL validation by replacing ${...} placeholders\n * with valid SQL identifiers that won't cause parse errors.\n */\nexport function prepareSqlForValidation(templateText: string): string {\n // Replace ${...} with a placeholder identifier that's valid in SQL\n // Using '_ph_N' pattern to create unique, valid identifiers\n let counter = 0;\n return templateText.replace(/\\$\\{\\.\\.\\.\\}/g, () => {\n counter++;\n return `_ph_${counter}`;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCO,SAAS,iBAAiB,aAA0C;AACzE,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,WAAW;AACrC,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,cAAc,MAAM,QAAQ,OAAO,YAAY,IAC3C,OAAO,aAAa;AAAA,QAClB,CAAC,SAA+C;AAAA,UAC9C,GAAI;AAAA,UACJ,SAAU,IAAI,WAAsC;AAAA,UACpD,SACG,IAAI,WACJ,IAAI,QACL;AAAA,UACF,WACG,IAAI,aACJ,IAAI,UACL;AAAA,UACF,cACG,IAAI,gBACJ,IAAI,UACL;AAAA,QACJ;AAAA,MACF,IACA,CAAC;AAAA,IACP;AAAA,EACF,QAAQ;AAEN,WAAO;AAAA,MACL,SAAS;AAAA,MACT,cAAc,CAAC;AAAA,IACjB;AAAA,EACF;AACF;AAMO,SAAS,wBAAwB,cAA8B;AAGpE,MAAI,UAAU;AACd,SAAO,aAAa,QAAQ,iBAAiB,MAAM;AACjD;AACA,WAAO,OAAO,OAAO;AAAA,EACvB,CAAC;AACH;","names":[]}
|
|
@@ -36,7 +36,11 @@ var import_sqlLocations = require("./sqlLocations");
|
|
|
36
36
|
column: 22,
|
|
37
37
|
endLine: 61,
|
|
38
38
|
endColumn: 6,
|
|
39
|
-
templateText: "\n SELECT \n ${...},\n ${...}\n FROM ${...}\n "
|
|
39
|
+
templateText: "\n SELECT \n ${...},\n ${...}\n FROM ${...}\n ",
|
|
40
|
+
tagKind: "bare",
|
|
41
|
+
tagLine: 54,
|
|
42
|
+
tagColumn: 18,
|
|
43
|
+
tagEndColumn: 21
|
|
40
44
|
}
|
|
41
45
|
]
|
|
42
46
|
};
|
|
@@ -46,6 +50,50 @@ var import_sqlLocations = require("./sqlLocations");
|
|
|
46
50
|
import_node_assert.default.strictEqual(result.sqlLocations[0].file, "/project/app/apis/bar.ts");
|
|
47
51
|
import_node_assert.default.strictEqual(result.sqlLocations[0].line, 54);
|
|
48
52
|
});
|
|
53
|
+
await t.test("parses tagKind from sql-locations.json", () => {
|
|
54
|
+
const json = JSON.stringify({
|
|
55
|
+
version: 1,
|
|
56
|
+
sqlLocations: [
|
|
57
|
+
{
|
|
58
|
+
id: "test.ts:1:1",
|
|
59
|
+
file: "/project/test.ts",
|
|
60
|
+
line: 1,
|
|
61
|
+
column: 1,
|
|
62
|
+
endLine: 1,
|
|
63
|
+
endColumn: 50,
|
|
64
|
+
templateText: "SELECT * FROM users",
|
|
65
|
+
tagKind: "statement"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
const manifest = (0, import_sqlLocations.loadSqlLocations)(json);
|
|
70
|
+
import_node_assert.default.strictEqual(manifest.sqlLocations[0].tagKind, "statement");
|
|
71
|
+
});
|
|
72
|
+
await t.test(
|
|
73
|
+
"applies defaults for missing tagKind and tag position fields",
|
|
74
|
+
() => {
|
|
75
|
+
const json = JSON.stringify({
|
|
76
|
+
version: 1,
|
|
77
|
+
sqlLocations: [
|
|
78
|
+
{
|
|
79
|
+
id: "test.ts:10:5",
|
|
80
|
+
file: "/project/test.ts",
|
|
81
|
+
line: 10,
|
|
82
|
+
column: 5,
|
|
83
|
+
endLine: 10,
|
|
84
|
+
endColumn: 50,
|
|
85
|
+
templateText: "SELECT * FROM users"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
const manifest = (0, import_sqlLocations.loadSqlLocations)(json);
|
|
90
|
+
const loc = manifest.sqlLocations[0];
|
|
91
|
+
import_node_assert.default.strictEqual(loc.tagKind, "statement");
|
|
92
|
+
import_node_assert.default.strictEqual(loc.tagLine, 10);
|
|
93
|
+
import_node_assert.default.strictEqual(loc.tagColumn, 5);
|
|
94
|
+
import_node_assert.default.strictEqual(loc.tagEndColumn, 5);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
49
97
|
await t.test("returns empty locations for invalid JSON", () => {
|
|
50
98
|
const result = (0, import_sqlLocations.loadSqlLocations)("not valid json");
|
|
51
99
|
import_node_assert.default.strictEqual(result.version, 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sqlLocations.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { test } from 'node:test';\nimport {\n loadSqlLocations,\n prepareSqlForValidation,\n type SqlLocationManifest,\n} from './sqlLocations';\n\ntest('loadSqlLocations Tests', async (t) => {\n await t.test('parses valid sql-locations.json content', () => {\n const manifest: SqlLocationManifest = {\n version: 1,\n sqlLocations: [\n {\n id: 'app/apis/bar.ts:54:22',\n file: '/project/app/apis/bar.ts',\n line: 54,\n column: 22,\n endLine: 61,\n endColumn: 6,\n templateText:\n '\\n SELECT \\n ${...},\\n ${...}\\n FROM ${...}\\n ',\n },\n ],\n };\n\n const result = loadSqlLocations(JSON.stringify(manifest));\n\n assert.strictEqual(result.version, 1);\n assert.strictEqual(result.sqlLocations.length, 1);\n assert.strictEqual(result.sqlLocations[0].file, '/project/app/apis/bar.ts');\n assert.strictEqual(result.sqlLocations[0].line, 54);\n });\n\n await t.test('returns empty locations for invalid JSON', () => {\n const result = loadSqlLocations('not valid json');\n\n assert.strictEqual(result.version, 1);\n assert.strictEqual(result.sqlLocations.length, 0);\n });\n\n await t.test('returns empty locations for missing sqlLocations field', () => {\n const result = loadSqlLocations('{\"version\": 1}');\n\n assert.strictEqual(result.sqlLocations.length, 0);\n });\n});\n\ntest('prepareSqlForValidation Tests', async (t) => {\n await t.test('replaces ${...} placeholders with valid identifiers', () => {\n const templateText = 'SELECT ${...} FROM ${...}';\n const result = prepareSqlForValidation(templateText);\n\n // Should replace ${...} with something the SQL parser can handle\n assert.ok(!result.includes('${...}'));\n // The result should be valid SQL structure\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('FROM'));\n });\n\n await t.test('preserves SQL keywords and structure', () => {\n const templateText = 'SELECT ${...} as col FROM ${...} WHERE x > 1';\n const result = prepareSqlForValidation(templateText);\n\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('as col'));\n assert.ok(result.includes('FROM'));\n assert.ok(result.includes('WHERE x > 1'));\n });\n\n await t.test('handles template with SLECT typo', () => {\n const templateText = 'SLECT ${...} FROM ${...}';\n const result = prepareSqlForValidation(templateText);\n\n // The typo should be preserved\n assert.ok(result.includes('SLECT'));\n });\n\n await t.test('handles multi-line templates', () => {\n const templateText = `\n SELECT \n \\${...},\n \\${...}\n FROM \\${...}\n ORDER BY \\${...} DESC\n `;\n const result = prepareSqlForValidation(templateText);\n\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('FROM'));\n assert.ok(result.includes('ORDER BY'));\n });\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,yBAAmB;AACnB,uBAAqB;AACrB,0BAIO;AAAA,IAEP,uBAAK,0BAA0B,OAAO,MAAM;AAC1C,QAAM,EAAE,KAAK,2CAA2C,MAAM;AAC5D,UAAM,WAAgC;AAAA,MACpC,SAAS;AAAA,MACT,cAAc;AAAA,QACZ;AAAA,UACE,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,WAAW;AAAA,UACX,cACE;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/sqlLocations.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { test } from 'node:test';\nimport {\n loadSqlLocations,\n prepareSqlForValidation,\n type SqlLocationManifest,\n} from './sqlLocations';\n\ntest('loadSqlLocations Tests', async (t) => {\n await t.test('parses valid sql-locations.json content', () => {\n const manifest: SqlLocationManifest = {\n version: 1,\n sqlLocations: [\n {\n id: 'app/apis/bar.ts:54:22',\n file: '/project/app/apis/bar.ts',\n line: 54,\n column: 22,\n endLine: 61,\n endColumn: 6,\n templateText:\n '\\n SELECT \\n ${...},\\n ${...}\\n FROM ${...}\\n ',\n tagKind: 'bare',\n tagLine: 54,\n tagColumn: 18,\n tagEndColumn: 21,\n },\n ],\n };\n\n const result = loadSqlLocations(JSON.stringify(manifest));\n\n assert.strictEqual(result.version, 1);\n assert.strictEqual(result.sqlLocations.length, 1);\n assert.strictEqual(result.sqlLocations[0].file, '/project/app/apis/bar.ts');\n assert.strictEqual(result.sqlLocations[0].line, 54);\n });\n\n await t.test('parses tagKind from sql-locations.json', () => {\n const json = JSON.stringify({\n version: 1,\n sqlLocations: [\n {\n id: 'test.ts:1:1',\n file: '/project/test.ts',\n line: 1,\n column: 1,\n endLine: 1,\n endColumn: 50,\n templateText: 'SELECT * FROM users',\n tagKind: 'statement',\n },\n ],\n });\n\n const manifest = loadSqlLocations(json);\n assert.strictEqual(manifest.sqlLocations[0].tagKind, 'statement');\n });\n\n await t.test(\n 'applies defaults for missing tagKind and tag position fields',\n () => {\n const json = JSON.stringify({\n version: 1,\n sqlLocations: [\n {\n id: 'test.ts:10:5',\n file: '/project/test.ts',\n line: 10,\n column: 5,\n endLine: 10,\n endColumn: 50,\n templateText: 'SELECT * FROM users',\n },\n ],\n });\n\n const manifest = loadSqlLocations(json);\n const loc = manifest.sqlLocations[0];\n assert.strictEqual(loc.tagKind, 'statement');\n assert.strictEqual(loc.tagLine, 10);\n assert.strictEqual(loc.tagColumn, 5);\n assert.strictEqual(loc.tagEndColumn, 5);\n },\n );\n\n await t.test('returns empty locations for invalid JSON', () => {\n const result = loadSqlLocations('not valid json');\n\n assert.strictEqual(result.version, 1);\n assert.strictEqual(result.sqlLocations.length, 0);\n });\n\n await t.test('returns empty locations for missing sqlLocations field', () => {\n const result = loadSqlLocations('{\"version\": 1}');\n\n assert.strictEqual(result.sqlLocations.length, 0);\n });\n});\n\ntest('prepareSqlForValidation Tests', async (t) => {\n await t.test('replaces ${...} placeholders with valid identifiers', () => {\n const templateText = 'SELECT ${...} FROM ${...}';\n const result = prepareSqlForValidation(templateText);\n\n // Should replace ${...} with something the SQL parser can handle\n assert.ok(!result.includes('${...}'));\n // The result should be valid SQL structure\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('FROM'));\n });\n\n await t.test('preserves SQL keywords and structure', () => {\n const templateText = 'SELECT ${...} as col FROM ${...} WHERE x > 1';\n const result = prepareSqlForValidation(templateText);\n\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('as col'));\n assert.ok(result.includes('FROM'));\n assert.ok(result.includes('WHERE x > 1'));\n });\n\n await t.test('handles template with SLECT typo', () => {\n const templateText = 'SLECT ${...} FROM ${...}';\n const result = prepareSqlForValidation(templateText);\n\n // The typo should be preserved\n assert.ok(result.includes('SLECT'));\n });\n\n await t.test('handles multi-line templates', () => {\n const templateText = `\n SELECT \n \\${...},\n \\${...}\n FROM \\${...}\n ORDER BY \\${...} DESC\n `;\n const result = prepareSqlForValidation(templateText);\n\n assert.ok(result.includes('SELECT'));\n assert.ok(result.includes('FROM'));\n assert.ok(result.includes('ORDER BY'));\n });\n});\n"],"mappings":"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","names":["assert"]}
|