fastify-auto-sqlapi 0.0.5 → 0.1.2
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/AGENTS.md +15 -2
- package/AGENTS_BACKEND.md +144 -20
- package/AGENTS_FRONTEND.md +161 -67
- package/README.md +47 -26
- package/dist/bin/generate-schema.js +9 -26
- package/dist/bin/generate-tables.js +7 -30
- package/dist/bin/utils.d.ts +28 -0
- package/dist/bin/utils.d.ts.map +1 -1
- package/dist/bin/utils.js +69 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/cli/load-dependency.d.ts +8 -0
- package/dist/lib/cli/load-dependency.d.ts.map +1 -0
- package/dist/lib/cli/load-dependency.js +21 -0
- package/dist/lib/cli/mysql-introspect.d.ts.map +1 -1
- package/dist/lib/cli/mysql-introspect.js +2 -18
- package/dist/lib/cli/pg-introspect.d.ts.map +1 -1
- package/dist/lib/cli/pg-introspect.js +2 -17
- package/dist/lib/db.d.ts +1 -0
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +33 -55
- package/dist/lib/dialect.d.ts +17 -0
- package/dist/lib/dialect.d.ts.map +1 -1
- package/dist/lib/dialect.js +32 -0
- package/dist/lib/engine/bulk/bulk-delete.d.ts.map +1 -1
- package/dist/lib/engine/bulk/bulk-delete.js +8 -2
- package/dist/lib/engine/bulk/bulk-upsert.d.ts.map +1 -1
- package/dist/lib/engine/bulk/bulk-upsert.js +15 -43
- package/dist/lib/engine/rest/delete.d.ts.map +1 -1
- package/dist/lib/engine/rest/delete.js +14 -12
- package/dist/lib/engine/rest/get.d.ts.map +1 -1
- package/dist/lib/engine/rest/get.js +3 -5
- package/dist/lib/engine/rest/insert.d.ts.map +1 -1
- package/dist/lib/engine/rest/insert.js +11 -31
- package/dist/lib/engine/rest/update.d.ts.map +1 -1
- package/dist/lib/engine/rest/update.js +13 -46
- package/dist/lib/engine/search/search.d.ts.map +1 -1
- package/dist/lib/engine/search/search.js +553 -229
- package/dist/lib/engine/write-helpers.d.ts +39 -2
- package/dist/lib/engine/write-helpers.d.ts.map +1 -1
- package/dist/lib/engine/write-helpers.js +55 -12
- package/dist/lib/errors.d.ts +11 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +12 -0
- package/dist/lib/schema/bulk-upsert.d.ts.map +1 -1
- package/dist/lib/schema/bulk-upsert.js +9 -25
- package/dist/lib/schema/helpers.d.ts +28 -1
- package/dist/lib/schema/helpers.d.ts.map +1 -1
- package/dist/lib/schema/helpers.js +38 -0
- package/dist/lib/schema/insert.d.ts.map +1 -1
- package/dist/lib/schema/insert.js +9 -19
- package/dist/lib/schema/search.d.ts.map +1 -1
- package/dist/lib/schema/search.js +138 -50
- package/dist/lib/schema/update.d.ts.map +1 -1
- package/dist/lib/schema/update.js +9 -25
- package/dist/lib/sql-api.d.ts +6 -6
- package/dist/lib/sql-api.d.ts.map +1 -1
- package/dist/lib/sql-api.js +10 -10
- package/dist/lib/table-helpers.d.ts +6 -1
- package/dist/lib/table-helpers.d.ts.map +1 -1
- package/dist/lib/table-helpers.js +42 -2
- package/dist/lib/tenant.d.ts +30 -0
- package/dist/lib/tenant.d.ts.map +1 -1
- package/dist/lib/tenant.js +78 -9
- package/dist/routes/auto/bulk-delete.routes.d.ts.map +1 -1
- package/dist/routes/auto/bulk-delete.routes.js +17 -23
- package/dist/routes/auto/bulk-upsert.routes.d.ts.map +1 -1
- package/dist/routes/auto/bulk-upsert.routes.js +16 -22
- package/dist/routes/auto/delete.routes.d.ts.map +1 -1
- package/dist/routes/auto/delete.routes.js +18 -24
- package/dist/routes/auto/get.routes.d.ts.map +1 -1
- package/dist/routes/auto/get.routes.js +16 -23
- package/dist/routes/auto/insert.routes.d.ts.map +1 -1
- package/dist/routes/auto/insert.routes.js +19 -26
- package/dist/routes/auto/plugin.d.ts.map +1 -1
- package/dist/routes/auto/plugin.js +40 -5
- package/dist/routes/auto/route-helpers.d.ts +27 -2
- package/dist/routes/auto/route-helpers.d.ts.map +1 -1
- package/dist/routes/auto/route-helpers.js +39 -1
- package/dist/routes/auto/search.routes.d.ts.map +1 -1
- package/dist/routes/auto/search.routes.js +47 -47
- package/dist/routes/auto/update.routes.d.ts.map +1 -1
- package/dist/routes/auto/update.routes.js +20 -27
- package/dist/types/cli.d.ts +22 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +1 -0
- package/dist/types/computed.d.ts +29 -0
- package/dist/types/computed.d.ts.map +1 -0
- package/dist/types/computed.js +1 -0
- package/dist/types/conditions.d.ts +16 -0
- package/dist/types/conditions.d.ts.map +1 -0
- package/dist/types/conditions.js +1 -0
- package/dist/types/db.d.ts +22 -0
- package/dist/types/db.d.ts.map +1 -0
- package/dist/types/db.js +1 -0
- package/dist/types/dml.d.ts +66 -0
- package/dist/types/dml.d.ts.map +1 -0
- package/dist/types/dml.js +1 -0
- package/dist/types/join.d.ts +44 -0
- package/dist/types/join.d.ts.map +1 -0
- package/dist/types/join.js +1 -0
- package/dist/types/plugin.d.ts +20 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +1 -0
- package/dist/types/schema.d.ts +10 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +1 -0
- package/dist/types/search.d.ts +45 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/search.js +1 -0
- package/dist/types/table.d.ts +76 -0
- package/dist/types/table.d.ts.map +1 -0
- package/dist/types/table.js +7 -0
- package/dist/types/tenant.d.ts +19 -0
- package/dist/types/tenant.d.ts.map +1 -0
- package/dist/types/tenant.js +1 -0
- package/dist/types/validation.d.ts +21 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +1 -0
- package/dist/types.d.ts +12 -277
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +12 -7
- package/package.json +3 -3
|
@@ -5,26 +5,13 @@ import { loadConfig } from '../lib/cli/config.js';
|
|
|
5
5
|
import { buildConnectionString, introspectTables } from '../lib/cli/pg-introspect.js';
|
|
6
6
|
import { buildMysqlConnectionConfig, introspectMysqlTables } from '../lib/cli/mysql-introspect.js';
|
|
7
7
|
import { buildTableMap, generateSchemaFile } from '../lib/cli/schema-codegen.js';
|
|
8
|
-
import { loadEnvFile, CONSOLE_COLORS, display, displayAsTableRow,
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
else if (args[i] === '--tables' && i + 1 < args.length) {
|
|
17
|
-
result.tables = args[++i].split(',').map((t) => t.trim()).filter(Boolean);
|
|
18
|
-
}
|
|
19
|
-
else if (args[i] === '--dialect' && i + 1 < args.length) {
|
|
20
|
-
result.dialect = args[++i];
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return result;
|
|
24
|
-
}
|
|
25
|
-
async function main() {
|
|
26
|
-
display('++++++ fastify-auto-sqlapi: generating schemas ++++++', CONSOLE_COLORS.yellow);
|
|
27
|
-
const cliArgs = parseCliArgs();
|
|
8
|
+
import { loadEnvFile, CONSOLE_COLORS, display, displayAsTableRow, parseArgs, runCli } from './utils.js';
|
|
9
|
+
await runCli('fastify-auto-sqlapi: generating schemas', async () => {
|
|
10
|
+
const cliArgs = parseArgs({
|
|
11
|
+
output: { type: 'value' },
|
|
12
|
+
tables: { type: 'list' },
|
|
13
|
+
dialect: { type: 'value' },
|
|
14
|
+
});
|
|
28
15
|
const config = await loadConfig();
|
|
29
16
|
loadEnvFile(config.envFile);
|
|
30
17
|
const dialect = (cliArgs.dialect || config.dialect || 'postgres');
|
|
@@ -51,7 +38,7 @@ async function main() {
|
|
|
51
38
|
const tableMap = buildTableMap(rows);
|
|
52
39
|
// Filter tables if --tables flag is provided
|
|
53
40
|
const tableNames = cliArgs.tables;
|
|
54
|
-
if (tableNames) {
|
|
41
|
+
if (tableNames.length) {
|
|
55
42
|
for (const schemaName of Object.keys(tableMap)) {
|
|
56
43
|
if (!tableNames.includes(tableMap[schemaName].name)) {
|
|
57
44
|
delete tableMap[schemaName];
|
|
@@ -94,7 +81,7 @@ async function main() {
|
|
|
94
81
|
}
|
|
95
82
|
}
|
|
96
83
|
// Remove orphan Schema*.ts files (only when generating all tables)
|
|
97
|
-
if (!tableNames) {
|
|
84
|
+
if (!tableNames.length) {
|
|
98
85
|
const existingFiles = fs.readdirSync(schemasDir);
|
|
99
86
|
for (const file of existingFiles) {
|
|
100
87
|
if (file.startsWith('Schema') && file.endsWith('.ts') && !generatedFiles.has(file)) {
|
|
@@ -115,8 +102,4 @@ async function main() {
|
|
|
115
102
|
if (!somethingTouched) {
|
|
116
103
|
display('All schemas are already up to date.', CONSOLE_COLORS.magenta);
|
|
117
104
|
}
|
|
118
|
-
}
|
|
119
|
-
main().catch((e) => {
|
|
120
|
-
error(`Error: ${e.message}`);
|
|
121
|
-
process.exit(1);
|
|
122
105
|
});
|
|
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { loadConfig } from '../lib/cli/config.js';
|
|
5
5
|
import { parseSchemaFile, generateSingleTableFile, generateDbTablesIndex } from '../lib/cli/tables-codegen.js';
|
|
6
|
-
import { loadEnvFile, CONSOLE_COLORS, display, displayAsTableRow, error } from './utils.js';
|
|
6
|
+
import { loadEnvFile, CONSOLE_COLORS, display, displayAsTableRow, error, parseArgs, runCli } from './utils.js';
|
|
7
7
|
function printHelp() {
|
|
8
8
|
console.log('');
|
|
9
9
|
display('Usage:', CONSOLE_COLORS.yellow);
|
|
@@ -22,35 +22,16 @@ function printHelp() {
|
|
|
22
22
|
display('Table*.ts files are only created if they do not already exist.', CONSOLE_COLORS.magenta);
|
|
23
23
|
display('dbTables.ts is always regenerated to include all schemas.', CONSOLE_COLORS.magenta);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
else if (args[i] === '--all') {
|
|
33
|
-
result.all = true;
|
|
34
|
-
}
|
|
35
|
-
else if (!args[i].startsWith('--')) {
|
|
36
|
-
// Split by comma to support both "a b" and "a,b" and "a, b"
|
|
37
|
-
for (const part of args[i].split(',')) {
|
|
38
|
-
const trimmed = part.trim();
|
|
39
|
-
if (trimmed)
|
|
40
|
-
result.tables.push(trimmed);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
}
|
|
46
|
-
async function main() {
|
|
47
|
-
const cliArgs = parseCliArgs();
|
|
25
|
+
await runCli('fastify-auto-sqlapi: generating tables template', async () => {
|
|
26
|
+
const cliArgs = parseArgs({
|
|
27
|
+
output: { type: 'value' },
|
|
28
|
+
all: { type: 'flag' },
|
|
29
|
+
tables: { type: 'list' },
|
|
30
|
+
});
|
|
48
31
|
if (!cliArgs.all && cliArgs.tables.length === 0) {
|
|
49
|
-
display('++++++ fastify-auto-sqlapi: generate tables template ++++++', CONSOLE_COLORS.yellow);
|
|
50
32
|
printHelp();
|
|
51
33
|
process.exit(1);
|
|
52
34
|
}
|
|
53
|
-
display('++++++ fastify-auto-sqlapi: generating tables template ++++++', CONSOLE_COLORS.yellow);
|
|
54
35
|
const config = await loadConfig();
|
|
55
36
|
loadEnvFile(config.envFile);
|
|
56
37
|
const outputDir = path.resolve(process.cwd(), cliArgs.output || config.outputDir);
|
|
@@ -128,8 +109,4 @@ async function main() {
|
|
|
128
109
|
}
|
|
129
110
|
console.log('');
|
|
130
111
|
display('Edit the generated Table*.ts files to customize your table configuration.', CONSOLE_COLORS.magenta);
|
|
131
|
-
}
|
|
132
|
-
main().catch((e) => {
|
|
133
|
-
error(`Error: ${e.message}`);
|
|
134
|
-
process.exit(1);
|
|
135
112
|
});
|
package/dist/bin/utils.d.ts
CHANGED
|
@@ -15,4 +15,32 @@ export declare const CONSOLE_COLORS: {
|
|
|
15
15
|
export declare function displayAsTableRow(pref: string, value: string, distance: number, color?: number): void;
|
|
16
16
|
export declare function display(text: string, color?: number): void;
|
|
17
17
|
export declare function error(text: string): void;
|
|
18
|
+
type ArgSpec = {
|
|
19
|
+
type: 'value';
|
|
20
|
+
} | {
|
|
21
|
+
type: 'flag';
|
|
22
|
+
} | {
|
|
23
|
+
type: 'list';
|
|
24
|
+
};
|
|
25
|
+
type ArgValue<S extends ArgSpec> = S['type'] extends 'flag' ? boolean : S['type'] extends 'list' ? string[] : string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Tiny declarative argv parser for the bundled CLIs.
|
|
28
|
+
* - `value` → recognized as `--name X`, last value wins
|
|
29
|
+
* - `flag` → recognized as `--name`, default false
|
|
30
|
+
* - `list` → comma-separated `--name a,b,c`; can also accept positional comma-/space- separated tokens
|
|
31
|
+
*
|
|
32
|
+
* Positional tokens (non-`--`) are accumulated into `positional`. List specs auto-merge those tokens
|
|
33
|
+
* (split on ',') into the list as well, supporting both "a b" and "a,b" CLI shapes.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseArgs<S extends Record<string, ArgSpec>>(spec: S, argv?: string[]): {
|
|
36
|
+
[K in keyof S]: ArgValue<S[K]>;
|
|
37
|
+
} & {
|
|
38
|
+
positional: string[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* CLI entry-point wrapper: prints a header, awaits `fn`, and turns thrown errors into a red message
|
|
42
|
+
* with a non-zero exit code (without aborting the process synchronously, so unfinished stdout flushes).
|
|
43
|
+
*/
|
|
44
|
+
export declare function runCli(name: string, fn: () => Promise<void>): Promise<void>;
|
|
45
|
+
export {};
|
|
18
46
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/bin/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/bin/utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAqBlD;AAED,eAAO,MAAM,cAAc;;;;;;;;CAQjB,CAAC;AAEX,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB,IAAI,CAQN;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI,CAE7D;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAExC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/bin/utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAqBlD;AAED,eAAO,MAAM,cAAc;;;;;;;;CAQjB,CAAC;AAEX,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB,IAAI,CAQN;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI,CAE7D;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAExC;AAED,KAAK,OAAO,GACR;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,KAAK,QAAQ,CAAC,CAAC,SAAS,OAAO,IAC7B,CAAC,CAAC,MAAM,CAAC,SAAS,MAAM,GAAG,OAAO,GAClC,CAAC,CAAC,MAAM,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,GACnC,MAAM,GAAG,SAAS,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,CAAC,EACP,IAAI,WAAwB,GAC3B;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAyC/D;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjF"}
|
package/dist/bin/utils.js
CHANGED
|
@@ -52,3 +52,72 @@ export function display(text, color = 0) {
|
|
|
52
52
|
export function error(text) {
|
|
53
53
|
display(text, CONSOLE_COLORS.red);
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Tiny declarative argv parser for the bundled CLIs.
|
|
57
|
+
* - `value` → recognized as `--name X`, last value wins
|
|
58
|
+
* - `flag` → recognized as `--name`, default false
|
|
59
|
+
* - `list` → comma-separated `--name a,b,c`; can also accept positional comma-/space- separated tokens
|
|
60
|
+
*
|
|
61
|
+
* Positional tokens (non-`--`) are accumulated into `positional`. List specs auto-merge those tokens
|
|
62
|
+
* (split on ',') into the list as well, supporting both "a b" and "a,b" CLI shapes.
|
|
63
|
+
*/
|
|
64
|
+
export function parseArgs(spec, argv = process.argv.slice(2)) {
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
const out = { positional: [] };
|
|
67
|
+
for (const [name, def] of Object.entries(spec)) {
|
|
68
|
+
out[name] = def.type === 'flag' ? false : def.type === 'list' ? [] : undefined;
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i < argv.length; i++) {
|
|
71
|
+
const token = argv[i];
|
|
72
|
+
if (token.startsWith('--')) {
|
|
73
|
+
const name = token.slice(2);
|
|
74
|
+
const def = spec[name];
|
|
75
|
+
if (!def)
|
|
76
|
+
continue;
|
|
77
|
+
if (def.type === 'flag') {
|
|
78
|
+
out[name] = true;
|
|
79
|
+
}
|
|
80
|
+
else if (def.type === 'value' && i + 1 < argv.length) {
|
|
81
|
+
out[name] = argv[++i];
|
|
82
|
+
}
|
|
83
|
+
else if (def.type === 'list' && i + 1 < argv.length) {
|
|
84
|
+
const next = argv[++i];
|
|
85
|
+
for (const part of next.split(',')) {
|
|
86
|
+
const t = part.trim();
|
|
87
|
+
if (t)
|
|
88
|
+
out[name].push(t);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
out.positional.push(token);
|
|
94
|
+
// Auto-distribute positional values into the (single) list spec, if any
|
|
95
|
+
for (const [n, def] of Object.entries(spec)) {
|
|
96
|
+
if (def.type === 'list') {
|
|
97
|
+
for (const part of token.split(',')) {
|
|
98
|
+
const t = part.trim();
|
|
99
|
+
if (t)
|
|
100
|
+
out[n].push(t);
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* CLI entry-point wrapper: prints a header, awaits `fn`, and turns thrown errors into a red message
|
|
112
|
+
* with a non-zero exit code (without aborting the process synchronously, so unfinished stdout flushes).
|
|
113
|
+
*/
|
|
114
|
+
export async function runCli(name, fn) {
|
|
115
|
+
display(`++++++ ${name} ++++++`, CONSOLE_COLORS.yellow);
|
|
116
|
+
try {
|
|
117
|
+
await fn();
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
error(`Error: ${e.message ?? String(e)}`);
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
}
|
|
123
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -30,5 +30,5 @@ export { BulkDeleteTableBody, BulkDeleteTableResponse } from './lib/schema/bulk-
|
|
|
30
30
|
export { default as bulkDeleteRoutes } from './routes/auto/bulk-delete.routes.js';
|
|
31
31
|
export { Type, type Static } from '@sinclair/typebox';
|
|
32
32
|
export { ConditionBuilder, Expression } from 'node-condition-builder';
|
|
33
|
-
export type { SqlApiConfig, ColumnInfo, TableMap, Queryable, SqlResult, DbRecord, DbRecordValue, SelectOptions, SchemaDefinition, JoinDefinition, ITable, DbTables, SqlApiPluginOptions, SwaggerOptions, SearchParams, SearchResult, Paginator, PaginationResult, TableFilterFn, ExtendedConditionFn, FilterRecord, AggregationRequest, JoinGroupRequest, GetParams, GetResult, DeleteParams, DeleteResult, InsertParams, InsertResult, BulkUpsertItem, BulkUpsertParams, BulkUpsertResult, BulkDeleteParams, BulkDeleteResult, ConditionMethod, SearchCondition, UpdateParams, UpdateResult, TenantId, TenantScope, TenantScopeDirect, TenantScopeIndirect, TenantContext, ValidationError, ValidatorFn, BulkValidatorItem, BulkValidatorFn, } from './types.js';
|
|
33
|
+
export type { SqlApiConfig, ColumnInfo, TableMap, Queryable, SqlResult, DbRecord, DbRecordValue, SelectOptions, SchemaDefinition, JoinDefinition, ITable, DbTables, SqlApiPluginOptions, SwaggerOptions, SearchParams, SearchResult, Paginator, PaginationResult, TableFilterFn, ExtendedConditionFn, FilterRecord, AggregationRequest, JoinGroupRequest, ComputedFieldFn, ComputedFieldContext, ComputedFieldExpr, GetParams, GetResult, DeleteParams, DeleteResult, InsertParams, InsertResult, BulkUpsertItem, BulkUpsertParams, BulkUpsertResult, BulkDeleteParams, BulkDeleteResult, ConditionMethod, SearchCondition, UpdateParams, UpdateResult, TenantId, TenantScope, TenantScopeDirect, TenantScopeIndirect, TenantContext, ValidationError, ValidatorFn, BulkValidatorItem, BulkValidatorFn, } from './types.js';
|
|
34
34
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load an optional peer dependency by trying the consumer's CWD first
|
|
3
|
+
* (so it works when installed via `npm install`/`npm link`), then falling
|
|
4
|
+
* back to the plugin's own `node_modules` (so it works in the plugin's own tests).
|
|
5
|
+
* Throws a friendly error if neither succeeds.
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadOptionalDependency<T = unknown>(modulePath: string, installHint: string): T;
|
|
8
|
+
//# sourceMappingURL=load-dependency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-dependency.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/load-dependency.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,CAAC,CAW9F"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
/**
|
|
3
|
+
* Load an optional peer dependency by trying the consumer's CWD first
|
|
4
|
+
* (so it works when installed via `npm install`/`npm link`), then falling
|
|
5
|
+
* back to the plugin's own `node_modules` (so it works in the plugin's own tests).
|
|
6
|
+
* Throws a friendly error if neither succeeds.
|
|
7
|
+
*/
|
|
8
|
+
export function loadOptionalDependency(modulePath, installHint) {
|
|
9
|
+
try {
|
|
10
|
+
return createRequire(process.cwd() + '/noop.js')(modulePath);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
/* fall through to local require */
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return createRequire(import.meta.url)(modulePath);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error(`${modulePath} is required. Install it with: ${installHint}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-introspect.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/mysql-introspect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,IAAI;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAmBA;AAkDD,wBAAsB,qBAAqB,CACzC,gBAAgB,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAClG,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"mysql-introspect.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/mysql-introspect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,IAAI;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAmBA;AAkDD,wBAAsB,qBAAqB,CACzC,gBAAgB,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAClG,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,CAyBvB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadOptionalDependency } from './load-dependency.js';
|
|
2
2
|
export function buildMysqlConnectionConfig() {
|
|
3
3
|
if (process.env.DATABASE_URL) {
|
|
4
4
|
const url = new URL(process.env.DATABASE_URL);
|
|
@@ -66,24 +66,8 @@ function mapMysqlType(dataType) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
export async function introspectMysqlTables(connectionConfig, schema) {
|
|
69
|
-
// Dynamic import: mysql2 is optional peer dependency.
|
|
70
|
-
// Try the consumer's CWD first (so it works when installed), then fall back to
|
|
71
|
-
// the plugin's own node_modules (so it works in the plugin's own tests).
|
|
72
69
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
const require = createRequire(process.cwd() + '/noop.js');
|
|
76
|
-
mysql2 = require('mysql2/promise');
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
try {
|
|
80
|
-
const require = createRequire(import.meta.url);
|
|
81
|
-
mysql2 = require('mysql2/promise');
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
throw new Error('mysql2 is required for MySQL/MariaDB introspection. Install it with: npm install mysql2');
|
|
85
|
-
}
|
|
86
|
-
}
|
|
70
|
+
const mysql2 = loadOptionalDependency('mysql2/promise', 'npm install mysql2');
|
|
87
71
|
const connection = await mysql2.createConnection(connectionConfig);
|
|
88
72
|
try {
|
|
89
73
|
const [rows] = await connection.query(`SELECT table_name, column_name, data_type, column_default, is_nullable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-introspect.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/pg-introspect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,qBAAqB,IAAI,MAAM,CAY9C;AAED,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"pg-introspect.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/pg-introspect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,qBAAqB,IAAI,MAAM,CAY9C;AAED,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadOptionalDependency } from './load-dependency.js';
|
|
2
2
|
export function buildConnectionString() {
|
|
3
3
|
if (process.env.DATABASE_URL) {
|
|
4
4
|
return process.env.DATABASE_URL;
|
|
@@ -11,23 +11,8 @@ export function buildConnectionString() {
|
|
|
11
11
|
return `postgres://${user}:${password}@${host}:${port}/${db}`;
|
|
12
12
|
}
|
|
13
13
|
export async function introspectTables(connectionString, schema) {
|
|
14
|
-
// Dynamic require from cwd so it works with npm link
|
|
15
14
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const require = createRequire(process.cwd() + '/noop.js');
|
|
19
|
-
pg = require('pg');
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
try {
|
|
23
|
-
// Fallback: resolve from the package's own node_modules
|
|
24
|
-
const require = createRequire(import.meta.url);
|
|
25
|
-
pg = require('pg');
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
throw new Error('pg is required for PostgreSQL introspection. Install it with: npm install pg');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
15
|
+
const pg = loadOptionalDependency('pg', 'npm install pg');
|
|
31
16
|
const client = new pg.Client({ connectionString });
|
|
32
17
|
try {
|
|
33
18
|
await client.connect();
|
package/dist/lib/db.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare class QueryClient {
|
|
|
13
13
|
get qi(): (id: string) => string;
|
|
14
14
|
get ph(): (i: number) => string;
|
|
15
15
|
get dialectName(): string;
|
|
16
|
+
get dateTrunc(): SqlDialect['dateTrunc'];
|
|
16
17
|
setDebug(mode: boolean): void;
|
|
17
18
|
expression(value: string): Expression;
|
|
18
19
|
query<T = Record<string, unknown>>(text: string, values?: unknown[]): Promise<SqlResult<T>>;
|
package/dist/lib/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/lib/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAQ/C,sCAAsC;AACtC,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,WAA0B,CAAC;AAEhE,qBAAa,WAAW;;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,UAAU;IAKnD,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAE/B;IAED,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAE9B;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,SAAS,IAAI,UAAU,CAAC,WAAW,CAAC,CAEvC;IAED,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI7B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAIrC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAmGlB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,EAChB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgB7B,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,EAChB,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAkB7B,UAAU,CACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,EAAE,EACnB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,SAAS,SAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAoB/B,kBAAkB,CACtB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,EAAE,EACnB,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EACxB,SAAS,SAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAuB/B,MAAM,CACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,EAChB,KAAK,EAAE,QAAQ,EACf,cAAc,CAAC,EAAE,gBAAgB,GAChC,OAAO,CAAC,MAAM,CAAC;IAuBZ,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,MAAM,CAAC;IAYZ,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACxC,SAAS,EACT,OAAa,EACb,KAAK,EACL,MAAM,EACN,KAAY,EACZ,OAAY,EACZ,KAAU,EACV,QAAgB,GACjB,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;CAchC;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,EACf,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,CAGb"}
|
package/dist/lib/db.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Expression } from 'node-condition-builder';
|
|
2
2
|
import { getDialect } from './dialect.js';
|
|
3
|
+
// Default chunk size for bulk INSERT/UPSERT. Picked to keep parameter count well under
|
|
4
|
+
// PostgreSQL's hard limit of 65535 bind parameters per statement (≈ 130 columns × 500 rows).
|
|
5
|
+
// Override per-call via the `chunkSize` argument when working with extremely wide tables.
|
|
3
6
|
const DEFAULT_CHUNK_SIZE = 500;
|
|
4
7
|
/** @deprecated Use db.qi() instead */
|
|
5
8
|
export const escapeIdent = (f) => f.replace(/"/g, '""');
|
|
@@ -20,6 +23,9 @@ export class QueryClient {
|
|
|
20
23
|
get dialectName() {
|
|
21
24
|
return this.dialect.name;
|
|
22
25
|
}
|
|
26
|
+
get dateTrunc() {
|
|
27
|
+
return this.dialect.dateTrunc.bind(this.dialect);
|
|
28
|
+
}
|
|
23
29
|
setDebug(mode) {
|
|
24
30
|
this.debug = mode;
|
|
25
31
|
}
|
|
@@ -73,26 +79,14 @@ export class QueryClient {
|
|
|
73
79
|
}
|
|
74
80
|
return { values, rows: rowPlaceholders.join(', ') };
|
|
75
81
|
}
|
|
76
|
-
// Build the update SET for upsert: dialect-specific
|
|
77
|
-
#upsertUpdateSet(fields, conflictKeys) {
|
|
78
|
-
const updateCols = fields.filter((f) => !conflictKeys.includes(f));
|
|
79
|
-
if (!updateCols.length)
|
|
80
|
-
return '';
|
|
81
|
-
if (this.dialect.name === 'postgres') {
|
|
82
|
-
return updateCols
|
|
83
|
-
.map((f) => `${this.dialect.qi(f)} = EXCLUDED.${this.dialect.qi(f)}`)
|
|
84
|
-
.join(', ');
|
|
85
|
-
}
|
|
86
|
-
// MySQL/MariaDB: VALUES(col) syntax
|
|
87
|
-
return updateCols
|
|
88
|
-
.map((f) => `${this.dialect.qi(f)} = VALUES(${this.dialect.qi(f)})`)
|
|
89
|
-
.join(', ');
|
|
90
|
-
}
|
|
91
82
|
#quotedPkCols(pkCol) {
|
|
92
83
|
const cols = Array.isArray(pkCol) ? pkCol : [pkCol];
|
|
93
84
|
return cols.map((c) => this.dialect.qi(c)).join(', ');
|
|
94
85
|
}
|
|
95
|
-
#
|
|
86
|
+
#insertHead(table, fields) {
|
|
87
|
+
return `INSERT INTO ${this.dialect.qi(table)} (${this.#q(fields)})`;
|
|
88
|
+
}
|
|
89
|
+
#mysqlPkRow(pkCol, record, insertId) {
|
|
96
90
|
const cols = Array.isArray(pkCol) ? pkCol : [pkCol];
|
|
97
91
|
const result = {};
|
|
98
92
|
for (const col of cols) {
|
|
@@ -106,57 +100,51 @@ export class QueryClient {
|
|
|
106
100
|
return { [pkCol]: insertId };
|
|
107
101
|
return result;
|
|
108
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Single source of truth for "extract PK rows from an insert/upsert result". When the
|
|
105
|
+
* dialect supports RETURNING (postgres/mariadb), returns `result.rows` directly. Otherwise
|
|
106
|
+
* (mysql) synthesizes PK rows from `insertId` + the input records (assumes
|
|
107
|
+
* `auto_increment_increment=1` for multi-row inserts).
|
|
108
|
+
*/
|
|
109
|
+
#extractPkRows(result, pkCol, inputs) {
|
|
110
|
+
if (this.dialect.supportsReturning)
|
|
111
|
+
return result.rows;
|
|
112
|
+
const firstId = result.insertId;
|
|
113
|
+
return inputs.map((rec, j) => this.#mysqlPkRow(pkCol, rec, typeof firstId === 'number' ? firstId + j : undefined));
|
|
114
|
+
}
|
|
109
115
|
async insert(table, record, pkCol) {
|
|
110
116
|
const values = [];
|
|
111
117
|
const { fields, placeholders } = this.#params(record, values);
|
|
112
118
|
if (!fields.length)
|
|
113
119
|
throw new Error('Cannot execute empty insert');
|
|
114
120
|
const returning = this.dialect.returningPk(this.#quotedPkCols(pkCol));
|
|
115
|
-
const result = await this.query(
|
|
121
|
+
const result = await this.query(`${this.#insertHead(table, fields)}
|
|
116
122
|
VALUES (${placeholders.join(', ')})${returning}`, values);
|
|
117
|
-
|
|
118
|
-
return result.rows[0];
|
|
119
|
-
}
|
|
120
|
-
return this.#mysqlPkResult(pkCol, record, result.insertId);
|
|
123
|
+
return this.#extractPkRows(result, pkCol, [record])[0];
|
|
121
124
|
}
|
|
122
125
|
async insertOrUpdate(table, record, conflictKeys, pkCol) {
|
|
123
126
|
const values = [];
|
|
124
127
|
const { fields, placeholders } = this.#params(record, values);
|
|
125
128
|
if (!fields.length)
|
|
126
129
|
throw new Error('Cannot execute empty insert');
|
|
127
|
-
const
|
|
128
|
-
const upsertClause = this.dialect.upsertSql(this.#q(conflictKeys), updateSet);
|
|
130
|
+
const upsertClause = this.dialect.upsertSql(this.#q(conflictKeys), this.dialect.upsertUpdateSet(fields, conflictKeys));
|
|
129
131
|
const returning = this.dialect.returningPk(this.#quotedPkCols(pkCol));
|
|
130
|
-
const result = await this.query(
|
|
132
|
+
const result = await this.query(`${this.#insertHead(table, fields)}
|
|
131
133
|
VALUES (${placeholders.join(', ')})
|
|
132
134
|
${upsertClause}${returning}`, values);
|
|
133
|
-
|
|
134
|
-
return result.rows[0];
|
|
135
|
-
}
|
|
136
|
-
return this.#mysqlPkResult(pkCol, record, result.insertId);
|
|
135
|
+
return this.#extractPkRows(result, pkCol, [record])[0];
|
|
137
136
|
}
|
|
138
137
|
async bulkInsert(table, records, pkCol, chunkSize = DEFAULT_CHUNK_SIZE) {
|
|
139
138
|
if (!records.length)
|
|
140
139
|
return [];
|
|
141
140
|
const fields = Object.keys(records[0]);
|
|
142
|
-
const results = [];
|
|
143
141
|
const returning = this.dialect.returningPk(this.#quotedPkCols(pkCol));
|
|
142
|
+
const results = [];
|
|
144
143
|
for (let i = 0; i < records.length; i += chunkSize) {
|
|
145
144
|
const chunk = records.slice(i, i + chunkSize);
|
|
146
145
|
const { values, rows } = this.#bulkValues(fields, chunk);
|
|
147
|
-
const result = await this.query(
|
|
148
|
-
|
|
149
|
-
results.push(...result.rows);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
// MySQL: insertId is the FIRST generated ID of the multi-row insert.
|
|
153
|
-
// Subsequent rows follow sequentially assuming auto_increment_increment=1 (default).
|
|
154
|
-
const firstId = result.insertId;
|
|
155
|
-
for (let j = 0; j < chunk.length; j++) {
|
|
156
|
-
const id = typeof firstId === 'number' ? firstId + j : undefined;
|
|
157
|
-
results.push(this.#mysqlPkResult(pkCol, chunk[j], id));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
146
|
+
const result = await this.query(`${this.#insertHead(table, fields)} VALUES ${rows}${returning}`, values);
|
|
147
|
+
results.push(...this.#extractPkRows(result, pkCol, chunk));
|
|
160
148
|
}
|
|
161
149
|
return results;
|
|
162
150
|
}
|
|
@@ -164,26 +152,16 @@ export class QueryClient {
|
|
|
164
152
|
if (!records.length)
|
|
165
153
|
return [];
|
|
166
154
|
const fields = Object.keys(records[0]);
|
|
167
|
-
const
|
|
168
|
-
const upsertClause = this.dialect.upsertSql(this.#q(conflictKeys), updateSet);
|
|
155
|
+
const upsertClause = this.dialect.upsertSql(this.#q(conflictKeys), this.dialect.upsertUpdateSet(fields, conflictKeys));
|
|
169
156
|
const returning = this.dialect.returningPk(this.#quotedPkCols(pkCol));
|
|
170
157
|
const results = [];
|
|
171
158
|
for (let i = 0; i < records.length; i += chunkSize) {
|
|
172
159
|
const chunk = records.slice(i, i + chunkSize);
|
|
173
160
|
const { values, rows } = this.#bulkValues(fields, chunk);
|
|
174
|
-
const result = await this.query(
|
|
161
|
+
const result = await this.query(`${this.#insertHead(table, fields)}
|
|
175
162
|
VALUES ${rows}
|
|
176
163
|
${upsertClause}${returning}`, values);
|
|
177
|
-
|
|
178
|
-
results.push(...result.rows);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
const firstId = result.insertId;
|
|
182
|
-
for (let j = 0; j < chunk.length; j++) {
|
|
183
|
-
const id = typeof firstId === 'number' ? firstId + j : undefined;
|
|
184
|
-
results.push(this.#mysqlPkResult(pkCol, chunk[j], id));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
164
|
+
results.push(...this.#extractPkRows(result, pkCol, chunk));
|
|
187
165
|
}
|
|
188
166
|
return results;
|
|
189
167
|
}
|
package/dist/lib/dialect.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type DialectName = 'postgres' | 'mysql' | 'mariadb';
|
|
2
|
+
export type TruncateUnit = 'year' | 'quarter' | 'month' | 'day' | 'hour';
|
|
2
3
|
export interface SqlDialect {
|
|
3
4
|
name: DialectName;
|
|
4
5
|
/** Quote identifier: "id" (postgres) or `id` (mysql/mariadb) */
|
|
@@ -12,6 +13,22 @@ export interface SqlDialect {
|
|
|
12
13
|
upsertSql(quotedConflictKeys: string, quotedUpdateSet: string): string;
|
|
13
14
|
/** RETURNING pk_col suffix or empty string */
|
|
14
15
|
returningPk(quotedPkCol: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Build the SET body for an upsert: the column list (separated by ', ') that the dialect
|
|
18
|
+
* uses to copy "incoming row" values into a conflicting row.
|
|
19
|
+
* - postgres: `"col" = EXCLUDED."col"`
|
|
20
|
+
* - mysql/mariadb: `` `col` = VALUES(`col`) ``
|
|
21
|
+
* Returns '' when there is nothing to update (i.e. all `fields` are conflict keys).
|
|
22
|
+
*/
|
|
23
|
+
upsertUpdateSet(fields: string[], conflictKeys: string[]): string;
|
|
24
|
+
/**
|
|
25
|
+
* Truncate a timestamp/date column to the start of the given unit and
|
|
26
|
+
* return it as an ISO-style string. The output is always a STRING:
|
|
27
|
+
* - year/quarter/month/day → 'YYYY-MM-DD' (e.g. '2026-04-01')
|
|
28
|
+
* - hour → 'YYYY-MM-DDTHH:00:00'
|
|
29
|
+
* `qualifiedCol` is a fully-qualified, already-quoted column expression.
|
|
30
|
+
*/
|
|
31
|
+
dateTrunc(unit: TruncateUnit, qualifiedCol: string): string;
|
|
15
32
|
}
|
|
16
33
|
export declare function getDialect(name: DialectName): SqlDialect;
|
|
17
34
|
//# sourceMappingURL=dialect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../src/lib/dialect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,gEAAgE;IAChE,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,sDAAsD;IACtD,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,oCAAoC;IACpC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC;IAChC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,kBAAkB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACvE,8CAA8C;IAC9C,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../../src/lib/dialect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,gEAAgE;IAChE,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,sDAAsD;IACtD,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,oCAAoC;IACpC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC;IAChC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,kBAAkB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACvE,8CAA8C;IAC9C,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IACzC;;;;;;OAMG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAClE;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7D;AAqFD,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAIxD"}
|