sqlstack 3.0.0 → 3.1.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/cjs/decorators/query.d.ts.map +1 -1
- package/dist/cjs/decorators/query.js +258 -240
- package/dist/cjs/decorators/query.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/run.d.ts +29 -0
- package/dist/cjs/run.d.ts.map +1 -0
- package/dist/cjs/run.js +38 -0
- package/dist/cjs/run.js.map +1 -0
- package/dist/cjs/testing/index.d.ts +4 -0
- package/dist/cjs/testing/index.d.ts.map +1 -1
- package/dist/cjs/testing/index.js +5 -1
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/cjs/testing/schema/ddl.d.ts +1 -10
- package/dist/cjs/testing/schema/ddl.d.ts.map +1 -1
- package/dist/cjs/testing/schema/ddl.js +29 -13
- package/dist/cjs/testing/schema/ddl.js.map +1 -1
- package/dist/cjs/testing/schema/normalize.js +3 -3
- package/dist/cjs/testing/schema/normalize.js.map +1 -1
- package/dist/cjs/testing/schema/types.d.ts +1 -20
- package/dist/cjs/testing/schema/types.d.ts.map +1 -1
- package/dist/cjs/testing/schema/types.js +0 -4
- package/dist/cjs/testing/schema/types.js.map +1 -1
- package/dist/cjs/testing/sqlite/builder.d.ts +24 -0
- package/dist/cjs/testing/sqlite/builder.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/builder.js +134 -0
- package/dist/cjs/testing/sqlite/builder.js.map +1 -0
- package/dist/cjs/testing/sqlite/database.d.ts +18 -0
- package/dist/cjs/testing/sqlite/database.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/database.js +123 -0
- package/dist/cjs/testing/sqlite/database.js.map +1 -0
- package/dist/cjs/testing/sqlite/loadData.d.ts +7 -0
- package/dist/cjs/testing/sqlite/loadData.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/loadData.js +55 -0
- package/dist/cjs/testing/sqlite/loadData.js.map +1 -0
- package/dist/esm/decorators/query.js +258 -240
- package/dist/esm/decorators/query.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/run.js +34 -0
- package/dist/esm/run.js.map +1 -0
- package/dist/esm/testing/index.js +2 -0
- package/dist/esm/testing/index.js.map +1 -1
- package/dist/esm/testing/schema/ddl.js +29 -13
- package/dist/esm/testing/schema/ddl.js.map +1 -1
- package/dist/esm/testing/schema/normalize.js +3 -3
- package/dist/esm/testing/schema/normalize.js.map +1 -1
- package/dist/esm/testing/schema/types.js +0 -4
- package/dist/esm/testing/schema/types.js.map +1 -1
- package/dist/esm/testing/sqlite/builder.js +98 -0
- package/dist/esm/testing/sqlite/builder.js.map +1 -0
- package/dist/esm/testing/sqlite/database.js +85 -0
- package/dist/esm/testing/sqlite/database.js.map +1 -0
- package/dist/esm/testing/sqlite/loadData.js +48 -0
- package/dist/esm/testing/sqlite/loadData.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { createSqliteDb } from '../../adapters/sqlite.js';
|
|
5
|
+
import { SqlStackError } from '../../core/errors.js';
|
|
6
|
+
export class TestSqliteError extends SqlStackError {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'TestSqliteError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Temp directories for file-backed handles that were never disposed. Tests are
|
|
14
|
+
* expected to call `dispose()`, but a failed assertion can skip it; this keeps
|
|
15
|
+
* an abandoned directory from outliving the worker process.
|
|
16
|
+
*/
|
|
17
|
+
const abandonedDirectories = new Set();
|
|
18
|
+
let exitCleanupRegistered = false;
|
|
19
|
+
function trackDirectory(directory) {
|
|
20
|
+
abandonedDirectories.add(directory);
|
|
21
|
+
if (exitCleanupRegistered)
|
|
22
|
+
return;
|
|
23
|
+
exitCleanupRegistered = true;
|
|
24
|
+
process.once('exit', () => {
|
|
25
|
+
for (const dir of abandonedDirectories) {
|
|
26
|
+
try {
|
|
27
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
/* best-effort cleanup */
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function createDatabaseHandle(fileBacked) {
|
|
36
|
+
let directory;
|
|
37
|
+
let filename = ':memory:';
|
|
38
|
+
if (fileBacked) {
|
|
39
|
+
directory = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlstack-test-'));
|
|
40
|
+
filename = path.join(directory, 'database.sqlite');
|
|
41
|
+
trackDirectory(directory);
|
|
42
|
+
}
|
|
43
|
+
let db;
|
|
44
|
+
try {
|
|
45
|
+
db = await createSqliteDb(filename);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (directory) {
|
|
49
|
+
fs.rmSync(directory, { recursive: true, force: true });
|
|
50
|
+
abandonedDirectories.delete(directory);
|
|
51
|
+
}
|
|
52
|
+
const message = err.message;
|
|
53
|
+
if (message.includes('No SQLite driver available')) {
|
|
54
|
+
throw new TestSqliteError('testSqlite requires the optional peer "better-sqlite3".');
|
|
55
|
+
}
|
|
56
|
+
throw new TestSqliteError(`Failed to create SQLite test database: ${message}`);
|
|
57
|
+
}
|
|
58
|
+
let disposed = false;
|
|
59
|
+
return {
|
|
60
|
+
db,
|
|
61
|
+
conn: db.conn,
|
|
62
|
+
path: fileBacked ? filename : undefined,
|
|
63
|
+
async query(sql, params = []) {
|
|
64
|
+
if (disposed)
|
|
65
|
+
throw new TestSqliteError('Test SQLite database has been disposed.');
|
|
66
|
+
return db.query(sql, [...params]);
|
|
67
|
+
},
|
|
68
|
+
async dispose() {
|
|
69
|
+
if (disposed)
|
|
70
|
+
return;
|
|
71
|
+
disposed = true;
|
|
72
|
+
try {
|
|
73
|
+
await db.close();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* connection may already be closed */
|
|
77
|
+
}
|
|
78
|
+
if (directory) {
|
|
79
|
+
fs.rmSync(directory, { recursive: true, force: true });
|
|
80
|
+
abandonedDirectories.delete(directory);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../../src/testing/sqlite/database.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { createSqliteDb } from '../../adapters/sqlite';\nimport { SqlStackError } from '../../core/errors';\nimport type { Database } from '../../registry';\n\nexport class TestSqliteError extends SqlStackError {\n constructor(message: string) {\n super(message);\n this.name = 'TestSqliteError';\n }\n}\n\nexport interface TestSqliteDatabase {\n /** The live sqlstack SQLite adapter, suitable for direct injection. */\n readonly db: Database;\n /** The underlying better-sqlite3 (or sqlite3) connection. */\n readonly conn: unknown;\n /** Absolute database path in file mode; undefined for :memory:. */\n readonly path?: string;\n query(sql: string, params?: readonly unknown[]): Promise<unknown>;\n /** Close the connection and remove owned temporary files. Idempotent. */\n dispose(): Promise<void>;\n}\n\n/**\n * Temp directories for file-backed handles that were never disposed. Tests are\n * expected to call `dispose()`, but a failed assertion can skip it; this keeps\n * an abandoned directory from outliving the worker process.\n */\nconst abandonedDirectories = new Set<string>();\nlet exitCleanupRegistered = false;\n\nfunction trackDirectory(directory: string): void {\n abandonedDirectories.add(directory);\n if (exitCleanupRegistered) return;\n exitCleanupRegistered = true;\n process.once('exit', () => {\n for (const dir of abandonedDirectories) {\n try {\n fs.rmSync(dir, { recursive: true, force: true });\n } catch {\n /* best-effort cleanup */\n }\n }\n });\n}\n\nexport async function createDatabaseHandle(\n fileBacked: boolean\n): Promise<TestSqliteDatabase> {\n let directory: string | undefined;\n let filename = ':memory:';\n if (fileBacked) {\n directory = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlstack-test-'));\n filename = path.join(directory, 'database.sqlite');\n trackDirectory(directory);\n }\n\n let db: Database;\n try {\n db = await createSqliteDb(filename);\n } catch (err) {\n if (directory) {\n fs.rmSync(directory, { recursive: true, force: true });\n abandonedDirectories.delete(directory);\n }\n const message = (err as Error).message;\n if (message.includes('No SQLite driver available')) {\n throw new TestSqliteError('testSqlite requires the optional peer \"better-sqlite3\".');\n }\n throw new TestSqliteError(`Failed to create SQLite test database: ${message}`);\n }\n\n let disposed = false;\n return {\n db,\n conn: db.conn,\n path: fileBacked ? filename : undefined,\n async query(sql: string, params: readonly unknown[] = []) {\n if (disposed) throw new TestSqliteError('Test SQLite database has been disposed.');\n return db.query(sql, [...params]);\n },\n async dispose() {\n if (disposed) return;\n disposed = true;\n try {\n await db.close();\n } catch {\n /* connection may already be closed */\n }\n if (directory) {\n fs.rmSync(directory, { recursive: true, force: true });\n abandonedDirectories.delete(directory);\n }\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { quoteIdent } from '../schema/ddl.js';
|
|
2
|
+
import { TestDataError, composeRows, planInsertOrder, toOperations, } from '../postgres/loadData.js';
|
|
3
|
+
export { TestDataError, composeRows, planInsertOrder, toOperations };
|
|
4
|
+
export async function insertRows(query, schema, effective) {
|
|
5
|
+
const order = planInsertOrder(schema, [...effective.keys()]);
|
|
6
|
+
const declared = new Map(schema.tables.map((table) => [
|
|
7
|
+
table.name,
|
|
8
|
+
table.columns.map((column) => column.name),
|
|
9
|
+
]));
|
|
10
|
+
for (const tableName of order) {
|
|
11
|
+
const rows = effective.get(tableName);
|
|
12
|
+
const columnOrder = declared.get(tableName);
|
|
13
|
+
const batches = new Map();
|
|
14
|
+
for (const row of rows) {
|
|
15
|
+
const columns = columnOrder.filter((column) => row[column] !== undefined);
|
|
16
|
+
const signature = columns.join(',');
|
|
17
|
+
const batch = batches.get(signature) ?? { columns, rows: [] };
|
|
18
|
+
batch.rows.push(row);
|
|
19
|
+
batches.set(signature, batch);
|
|
20
|
+
}
|
|
21
|
+
for (const { columns, rows: batchRows } of batches.values()) {
|
|
22
|
+
if (columns.length === 0) {
|
|
23
|
+
for (let i = 0; i < batchRows.length; i++) {
|
|
24
|
+
await run(query, tableName, `INSERT INTO ${quoteIdent(tableName)} DEFAULT VALUES`, []);
|
|
25
|
+
}
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const params = [];
|
|
29
|
+
const tuples = batchRows.map((row) => {
|
|
30
|
+
const placeholders = columns.map((column) => {
|
|
31
|
+
params.push(row[column]);
|
|
32
|
+
return '?';
|
|
33
|
+
});
|
|
34
|
+
return `(${placeholders.join(', ')})`;
|
|
35
|
+
});
|
|
36
|
+
await run(query, tableName, `INSERT INTO ${quoteIdent(tableName)} (${columns.map(quoteIdent).join(', ')}) VALUES ${tuples.join(', ')}`, params);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function run(query, tableName, sql, params) {
|
|
41
|
+
try {
|
|
42
|
+
await query(sql, params);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
throw new TestDataError(`Failed to insert scenario rows into table "${tableName}": ${err.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=loadData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadData.js","sourceRoot":"","sources":["../../../../src/testing/sqlite/loadData.ts"],"names":[],"mappings":"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","sourcesContent":["import { quoteIdent } from '../schema/ddl';\nimport type { NormalizedTestSchema } from '../schema/types';\nimport {\n TestDataError,\n composeRows,\n planInsertOrder,\n toOperations,\n} from '../postgres/loadData';\nimport type { DataOperation, Row } from '../postgres/loadData';\n\nexport { TestDataError, composeRows, planInsertOrder, toOperations };\nexport type { DataOperation, Row };\n\nexport async function insertRows(\n query: (sql: string, params: unknown[]) => Promise<unknown>,\n schema: NormalizedTestSchema,\n effective: Map<string, Row[]>\n): Promise<void> {\n const order = planInsertOrder(schema, [...effective.keys()]);\n const declared = new Map(schema.tables.map((table) => [\n table.name,\n table.columns.map((column) => column.name),\n ]));\n for (const tableName of order) {\n const rows = effective.get(tableName)!;\n const columnOrder = declared.get(tableName)!;\n const batches = new Map<string, { columns: string[]; rows: Row[] }>();\n for (const row of rows) {\n const columns = columnOrder.filter((column) => row[column] !== undefined);\n const signature = columns.join(',');\n const batch = batches.get(signature) ?? { columns, rows: [] };\n batch.rows.push(row);\n batches.set(signature, batch);\n }\n for (const { columns, rows: batchRows } of batches.values()) {\n if (columns.length === 0) {\n for (let i = 0; i < batchRows.length; i++) {\n await run(query, tableName, `INSERT INTO ${quoteIdent(tableName)} DEFAULT VALUES`, []);\n }\n continue;\n }\n const params: unknown[] = [];\n const tuples = batchRows.map((row) => {\n const placeholders = columns.map((column) => {\n params.push(row[column]);\n return '?';\n });\n return `(${placeholders.join(', ')})`;\n });\n await run(\n query,\n tableName,\n `INSERT INTO ${quoteIdent(tableName)} (${columns.map(quoteIdent).join(', ')}) VALUES ${tuples.join(', ')}`,\n params\n );\n }\n }\n}\n\nasync function run(\n query: (sql: string, params: unknown[]) => Promise<unknown>,\n tableName: string,\n sql: string,\n params: unknown[]\n): Promise<void> {\n try {\n await query(sql, params);\n } catch (err) {\n throw new TestDataError(\n `Failed to insert scenario rows into table \"${tableName}\": ${(err as Error).message}`\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sqlstack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"build:cjs": "tsc -p tsconfig.json",
|
|
57
57
|
"build:esm": "tsc -p tsconfig.esm.json && node scripts/fix-esm-extensions.js && node scripts/create-esm-package.cjs",
|
|
58
58
|
"test": "jest",
|
|
59
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
59
60
|
"test:watch": "jest --watch",
|
|
60
61
|
"clean": "rimraf dist",
|
|
61
62
|
"test:integration": "jest -c jest.integration.config.ts",
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"db:logs:mysql": "docker logs -f sqlstack-mysql"
|
|
71
72
|
},
|
|
72
73
|
"devDependencies": {
|
|
73
|
-
"@noego/ioc": "
|
|
74
|
+
"@noego/ioc": "^0.6.1",
|
|
74
75
|
"@types/jest": "^29.5.13",
|
|
75
76
|
"better-sqlite3": "^12.3.0",
|
|
76
77
|
"jest": "^29.7.0",
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"yaml": "^2.9.0"
|
|
89
90
|
},
|
|
90
91
|
"peerDependencies": {
|
|
91
|
-
"@noego/ioc": "
|
|
92
|
+
"@noego/ioc": ">=0.6.1",
|
|
92
93
|
"better-sqlite3": "*",
|
|
93
94
|
"mysql2": "*",
|
|
94
95
|
"pg": "*",
|