fastify-auto-sqlapi 0.0.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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/dist/bin/generate-schema.d.ts +3 -0
  4. package/dist/bin/generate-schema.d.ts.map +1 -0
  5. package/dist/bin/generate-schema.js +122 -0
  6. package/dist/bin/generate-tables.d.ts +3 -0
  7. package/dist/bin/generate-tables.d.ts.map +1 -0
  8. package/dist/bin/generate-tables.js +135 -0
  9. package/dist/bin/utils.d.ts +18 -0
  10. package/dist/bin/utils.d.ts.map +1 -0
  11. package/dist/bin/utils.js +54 -0
  12. package/dist/index.d.ts +34 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +48 -0
  15. package/dist/lib/adapters/mysql-adapter.d.ts +9 -0
  16. package/dist/lib/adapters/mysql-adapter.d.ts.map +1 -0
  17. package/dist/lib/adapters/mysql-adapter.js +21 -0
  18. package/dist/lib/adapters/pg-adapter.d.ts +9 -0
  19. package/dist/lib/adapters/pg-adapter.d.ts.map +1 -0
  20. package/dist/lib/adapters/pg-adapter.js +11 -0
  21. package/dist/lib/cli/config.d.ts +3 -0
  22. package/dist/lib/cli/config.d.ts.map +1 -0
  23. package/dist/lib/cli/config.js +29 -0
  24. package/dist/lib/cli/mysql-introspect.d.ts +16 -0
  25. package/dist/lib/cli/mysql-introspect.d.ts.map +1 -0
  26. package/dist/lib/cli/mysql-introspect.js +98 -0
  27. package/dist/lib/cli/pg-introspect.d.ts +4 -0
  28. package/dist/lib/cli/pg-introspect.d.ts.map +1 -0
  29. package/dist/lib/cli/pg-introspect.js +36 -0
  30. package/dist/lib/cli/schema-codegen.d.ts +8 -0
  31. package/dist/lib/cli/schema-codegen.d.ts.map +1 -0
  32. package/dist/lib/cli/schema-codegen.js +100 -0
  33. package/dist/lib/cli/tables-codegen.d.ts +18 -0
  34. package/dist/lib/cli/tables-codegen.d.ts.map +1 -0
  35. package/dist/lib/cli/tables-codegen.js +249 -0
  36. package/dist/lib/condition-methods.d.ts +11 -0
  37. package/dist/lib/condition-methods.d.ts.map +1 -0
  38. package/dist/lib/condition-methods.js +20 -0
  39. package/dist/lib/db.d.ts +28 -0
  40. package/dist/lib/db.d.ts.map +1 -0
  41. package/dist/lib/db.js +224 -0
  42. package/dist/lib/dialect.d.ts +17 -0
  43. package/dist/lib/dialect.d.ts.map +1 -0
  44. package/dist/lib/dialect.js +56 -0
  45. package/dist/lib/engine/bulk/bulk-delete.d.ts +3 -0
  46. package/dist/lib/engine/bulk/bulk-delete.d.ts.map +1 -0
  47. package/dist/lib/engine/bulk/bulk-delete.js +30 -0
  48. package/dist/lib/engine/bulk/bulk-upsert.d.ts +3 -0
  49. package/dist/lib/engine/bulk/bulk-upsert.d.ts.map +1 -0
  50. package/dist/lib/engine/bulk/bulk-upsert.js +74 -0
  51. package/dist/lib/engine/rest/delete.d.ts +3 -0
  52. package/dist/lib/engine/rest/delete.d.ts.map +1 -0
  53. package/dist/lib/engine/rest/delete.js +25 -0
  54. package/dist/lib/engine/rest/get.d.ts +3 -0
  55. package/dist/lib/engine/rest/get.d.ts.map +1 -0
  56. package/dist/lib/engine/rest/get.js +32 -0
  57. package/dist/lib/engine/rest/insert.d.ts +3 -0
  58. package/dist/lib/engine/rest/insert.d.ts.map +1 -0
  59. package/dist/lib/engine/rest/insert.js +58 -0
  60. package/dist/lib/engine/rest/update.d.ts +3 -0
  61. package/dist/lib/engine/rest/update.d.ts.map +1 -0
  62. package/dist/lib/engine/rest/update.js +110 -0
  63. package/dist/lib/engine/search/search.d.ts +3 -0
  64. package/dist/lib/engine/search/search.d.ts.map +1 -0
  65. package/dist/lib/engine/search/search.js +300 -0
  66. package/dist/lib/engine/write-helpers.d.ts +8 -0
  67. package/dist/lib/engine/write-helpers.d.ts.map +1 -0
  68. package/dist/lib/engine/write-helpers.js +83 -0
  69. package/dist/lib/naming.d.ts +6 -0
  70. package/dist/lib/naming.d.ts.map +1 -0
  71. package/dist/lib/naming.js +23 -0
  72. package/dist/lib/schema/bulk-delete.d.ts +10 -0
  73. package/dist/lib/schema/bulk-delete.d.ts.map +1 -0
  74. package/dist/lib/schema/bulk-delete.js +16 -0
  75. package/dist/lib/schema/bulk-upsert.d.ts +5 -0
  76. package/dist/lib/schema/bulk-upsert.d.ts.map +1 -0
  77. package/dist/lib/schema/bulk-upsert.js +43 -0
  78. package/dist/lib/schema/helpers.d.ts +14 -0
  79. package/dist/lib/schema/helpers.d.ts.map +1 -0
  80. package/dist/lib/schema/helpers.js +33 -0
  81. package/dist/lib/schema/insert.d.ts +5 -0
  82. package/dist/lib/schema/insert.d.ts.map +1 -0
  83. package/dist/lib/schema/insert.js +43 -0
  84. package/dist/lib/schema/search.d.ts +14 -0
  85. package/dist/lib/schema/search.d.ts.map +1 -0
  86. package/dist/lib/schema/search.js +99 -0
  87. package/dist/lib/schema/update.d.ts +5 -0
  88. package/dist/lib/schema/update.d.ts.map +1 -0
  89. package/dist/lib/schema/update.js +47 -0
  90. package/dist/lib/setup-swagger.d.ts +4 -0
  91. package/dist/lib/setup-swagger.d.ts.map +1 -0
  92. package/dist/lib/setup-swagger.js +27 -0
  93. package/dist/lib/sql-api.d.ts +49 -0
  94. package/dist/lib/sql-api.d.ts.map +1 -0
  95. package/dist/lib/sql-api.js +124 -0
  96. package/dist/lib/table-helpers.d.ts +17 -0
  97. package/dist/lib/table-helpers.d.ts.map +1 -0
  98. package/dist/lib/table-helpers.js +34 -0
  99. package/dist/lib/tenant.d.ts +19 -0
  100. package/dist/lib/tenant.d.ts.map +1 -0
  101. package/dist/lib/tenant.js +110 -0
  102. package/dist/routes/auto/bulk-delete.routes.d.ts +4 -0
  103. package/dist/routes/auto/bulk-delete.routes.d.ts.map +1 -0
  104. package/dist/routes/auto/bulk-delete.routes.js +27 -0
  105. package/dist/routes/auto/bulk-upsert.routes.d.ts +4 -0
  106. package/dist/routes/auto/bulk-upsert.routes.d.ts.map +1 -0
  107. package/dist/routes/auto/bulk-upsert.routes.js +25 -0
  108. package/dist/routes/auto/delete.routes.d.ts +4 -0
  109. package/dist/routes/auto/delete.routes.d.ts.map +1 -0
  110. package/dist/routes/auto/delete.routes.js +29 -0
  111. package/dist/routes/auto/get.routes.d.ts +4 -0
  112. package/dist/routes/auto/get.routes.d.ts.map +1 -0
  113. package/dist/routes/auto/get.routes.js +26 -0
  114. package/dist/routes/auto/insert.routes.d.ts +4 -0
  115. package/dist/routes/auto/insert.routes.d.ts.map +1 -0
  116. package/dist/routes/auto/insert.routes.js +29 -0
  117. package/dist/routes/auto/plugin.d.ts +11 -0
  118. package/dist/routes/auto/plugin.d.ts.map +1 -0
  119. package/dist/routes/auto/plugin.js +81 -0
  120. package/dist/routes/auto/route-helpers.d.ts +7 -0
  121. package/dist/routes/auto/route-helpers.d.ts.map +1 -0
  122. package/dist/routes/auto/route-helpers.js +12 -0
  123. package/dist/routes/auto/search.routes.d.ts +4 -0
  124. package/dist/routes/auto/search.routes.d.ts.map +1 -0
  125. package/dist/routes/auto/search.routes.js +50 -0
  126. package/dist/routes/auto/update.routes.d.ts +4 -0
  127. package/dist/routes/auto/update.routes.d.ts.map +1 -0
  128. package/dist/routes/auto/update.routes.js +30 -0
  129. package/dist/types.d.ts +240 -0
  130. package/dist/types.d.ts.map +1 -0
  131. package/dist/types.js +7 -0
  132. package/package.json +106 -0
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { loadConfig } from '../lib/cli/config.js';
5
+ import { parseSchemaFile, generateSingleTableFile, generateDbTablesIndex } from '../lib/cli/tables-codegen.js';
6
+ import { loadEnvFile, CONSOLE_COLORS, display, displayAsTableRow, error } from './utils.js';
7
+ loadEnvFile();
8
+ function printHelp() {
9
+ console.log('');
10
+ display('Usage:', CONSOLE_COLORS.yellow);
11
+ console.log(' sqlapi-generate-tables <table1> [table2 ...] Generate specific tables (comma or space separated)');
12
+ console.log(' sqlapi-generate-tables --all Generate all tables');
13
+ console.log('');
14
+ display('Options:', CONSOLE_COLORS.yellow);
15
+ console.log(' --all Generate Table*.ts for all schemas found');
16
+ console.log(' --output <dir> Output directory (default: from sqlapi.config)');
17
+ console.log('');
18
+ display('Examples:', CONSOLE_COLORS.yellow);
19
+ console.log(' sqlapi-generate-tables customer customer_order');
20
+ console.log(' sqlapi-generate-tables customer,customer_order');
21
+ console.log(' sqlapi-generate-tables --all');
22
+ console.log('');
23
+ display('Table*.ts files are only created if they do not already exist.', CONSOLE_COLORS.magenta);
24
+ display('dbTables.ts is always regenerated to include all schemas.', CONSOLE_COLORS.magenta);
25
+ }
26
+ function parseCliArgs() {
27
+ const args = process.argv.slice(2);
28
+ const result = { all: false, tables: [] };
29
+ for (let i = 0; i < args.length; i++) {
30
+ if (args[i] === '--output' && i + 1 < args.length) {
31
+ result.output = args[++i];
32
+ }
33
+ else if (args[i] === '--all') {
34
+ result.all = true;
35
+ }
36
+ else if (!args[i].startsWith('--')) {
37
+ // Split by comma to support both "a b" and "a,b" and "a, b"
38
+ for (const part of args[i].split(',')) {
39
+ const trimmed = part.trim();
40
+ if (trimmed)
41
+ result.tables.push(trimmed);
42
+ }
43
+ }
44
+ }
45
+ return result;
46
+ }
47
+ async function main() {
48
+ const cliArgs = parseCliArgs();
49
+ if (!cliArgs.all && cliArgs.tables.length === 0) {
50
+ display('++++++ fastify-auto-sqlapi: generate tables template ++++++', CONSOLE_COLORS.yellow);
51
+ printHelp();
52
+ process.exit(1);
53
+ }
54
+ display('++++++ fastify-auto-sqlapi: generating tables template ++++++', CONSOLE_COLORS.yellow);
55
+ const config = await loadConfig();
56
+ const outputDir = path.resolve(process.cwd(), cliArgs.output || config.outputDir);
57
+ const schemasDir = path.join(outputDir, 'schemas');
58
+ const tablesDir = path.join(outputDir, 'tables');
59
+ if (!fs.existsSync(schemasDir)) {
60
+ error(`Schemas directory not found: ${schemasDir}`);
61
+ display('Run sqlapi-generate-schema first.', CONSOLE_COLORS.magenta);
62
+ process.exit(1);
63
+ }
64
+ if (!fs.existsSync(tablesDir)) {
65
+ fs.mkdirSync(tablesDir, { recursive: true });
66
+ display(`Created directory: ${tablesDir}`, CONSOLE_COLORS.green);
67
+ }
68
+ const schemaFiles = fs
69
+ .readdirSync(schemasDir)
70
+ .filter((f) => f.startsWith('Schema') && f.endsWith('.ts'))
71
+ .sort();
72
+ if (schemaFiles.length === 0) {
73
+ error('No Schema*.ts files found.');
74
+ display('Run sqlapi-generate-schema first.', CONSOLE_COLORS.magenta);
75
+ process.exit(1);
76
+ }
77
+ // Parse all schemas (needed for relation detection even when generating a subset)
78
+ const allSchemas = [];
79
+ for (const file of schemaFiles) {
80
+ const content = fs.readFileSync(path.join(schemasDir, file), 'utf-8');
81
+ const parsed = parseSchemaFile(content);
82
+ if (parsed) {
83
+ allSchemas.push(parsed);
84
+ }
85
+ }
86
+ if (allSchemas.length === 0) {
87
+ error('No valid schemas parsed.');
88
+ process.exit(1);
89
+ }
90
+ // Determine which schemas to generate Table files for
91
+ let targetSchemas;
92
+ if (cliArgs.all) {
93
+ targetSchemas = allSchemas;
94
+ }
95
+ else {
96
+ const requestedSet = new Set(cliArgs.tables);
97
+ targetSchemas = allSchemas.filter((s) => requestedSet.has(s.tableName));
98
+ const foundNames = new Set(targetSchemas.map((s) => s.tableName));
99
+ for (const name of requestedSet) {
100
+ if (!foundNames.has(name)) {
101
+ error(`Table "${name}" not found. Available: ${allSchemas.map((s) => s.tableName).join(', ')}`);
102
+ process.exit(1);
103
+ }
104
+ }
105
+ }
106
+ // Generate individual Table*.ts files (skip if already exists)
107
+ for (const schema of targetSchemas) {
108
+ const tableVarName = 'Table' + schema.schemaName.replace(/^Schema/, '');
109
+ const tableFile = path.join(tablesDir, `${tableVarName}.ts`);
110
+ if (fs.existsSync(tableFile)) {
111
+ displayAsTableRow(`${tableVarName}.ts`, 'skipped (already exists)', 60, CONSOLE_COLORS.gray);
112
+ }
113
+ else {
114
+ const content = generateSingleTableFile(schema, allSchemas);
115
+ fs.writeFileSync(tableFile, content);
116
+ displayAsTableRow(`${tableVarName}.ts`, 'created', 60, CONSOLE_COLORS.green);
117
+ }
118
+ }
119
+ // Generate dbTables.ts only if it does not exist
120
+ const dbTablesFile = path.join(tablesDir, 'dbTables.ts');
121
+ if (fs.existsSync(dbTablesFile)) {
122
+ displayAsTableRow('dbTables.ts', 'skipped (already exists)', 60, CONSOLE_COLORS.gray);
123
+ }
124
+ else {
125
+ const dbTablesContent = generateDbTablesIndex(allSchemas);
126
+ fs.writeFileSync(dbTablesFile, dbTablesContent);
127
+ displayAsTableRow('dbTables.ts', 'created', 60, CONSOLE_COLORS.green);
128
+ }
129
+ console.log('');
130
+ 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
+ });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Load .env file from cwd if it exists.
3
+ * Does not override already-set environment variables.
4
+ */
5
+ export declare function loadEnvFile(): void;
6
+ export declare const CONSOLE_COLORS: {
7
+ readonly black: 30;
8
+ readonly gray: 90;
9
+ readonly red: 31;
10
+ readonly green: 32;
11
+ readonly yellow: 33;
12
+ readonly magenta: 35;
13
+ readonly cyan: 36;
14
+ };
15
+ export declare function displayAsTableRow(pref: string, value: string, distance: number, color?: number): void;
16
+ export declare function display(text: string, color?: number): void;
17
+ export declare function error(text: string): void;
18
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/bin/utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAqBlC;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"}
@@ -0,0 +1,54 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ /**
4
+ * Load .env file from cwd if it exists.
5
+ * Does not override already-set environment variables.
6
+ */
7
+ export function loadEnvFile() {
8
+ const envPath = resolve(process.cwd(), '.env');
9
+ if (!existsSync(envPath))
10
+ return;
11
+ const content = readFileSync(envPath, 'utf-8');
12
+ for (const line of content.split('\n')) {
13
+ const trimmed = line.trim();
14
+ if (!trimmed || trimmed.startsWith('#'))
15
+ continue;
16
+ const eqIndex = trimmed.indexOf('=');
17
+ if (eqIndex === -1)
18
+ continue;
19
+ const key = trimmed.slice(0, eqIndex).trim();
20
+ let value = trimmed.slice(eqIndex + 1).trim();
21
+ // Strip surrounding quotes
22
+ if ((value.startsWith('"') && value.endsWith('"')) ||
23
+ (value.startsWith("'") && value.endsWith("'"))) {
24
+ value = value.slice(1, -1);
25
+ }
26
+ if (!(key in process.env)) {
27
+ process.env[key] = value;
28
+ }
29
+ }
30
+ }
31
+ export const CONSOLE_COLORS = {
32
+ black: 30,
33
+ gray: 90,
34
+ red: 31,
35
+ green: 32,
36
+ yellow: 33,
37
+ magenta: 35,
38
+ cyan: 36,
39
+ };
40
+ export function displayAsTableRow(pref, value, distance, color = 0) {
41
+ const len = pref.length;
42
+ let text = pref + ' \x1b[' + color + 'm';
43
+ for (let i = 0; i < distance - len; i++) {
44
+ text += '_';
45
+ }
46
+ text += ' ' + value + '\x1b[0m';
47
+ console.log(text);
48
+ }
49
+ export function display(text, color = 0) {
50
+ console.log('\x1b[' + color + 'm' + text + '\x1b[0m');
51
+ }
52
+ export function error(text) {
53
+ display(text, CONSOLE_COLORS.red);
54
+ }
@@ -0,0 +1,34 @@
1
+ export { toCamelCase, toUnderscore, toSchemaName, camelcaseObject, snakecaseRecord, } from './lib/naming.js';
2
+ export { QueryClient, createQueryClient, escapeIdent } from './lib/db.js';
3
+ export { getDialect, type SqlDialect, type DialectName } from './lib/dialect.js';
4
+ export { pgQueryable } from './lib/adapters/pg-adapter.js';
5
+ export { mysqlQueryable } from './lib/adapters/mysql-adapter.js';
6
+ export { exportTableInfo, defineTable, buildRelation, buildUpsertRule, buildUpsertRules } from './lib/table-helpers.js';
7
+ export { resolveTenant } from './lib/tenant.js';
8
+ export { SqlApi, createSqlApi } from './lib/sql-api.js';
9
+ export type { SqlApiOptions, SqlApiSearchParams, SqlApiInsertParams, SqlApiUpdateParams } from './lib/sql-api.js';
10
+ export { default as fastifyAutoSqlApi } from './routes/auto/plugin.js';
11
+ export { setupSwagger } from './lib/setup-swagger.js';
12
+ export { searchEngine } from './lib/engine/search/search.js';
13
+ export { SearchTableBodyPost, SearchTableQueryString, SearchTableResponse } from './lib/schema/search.js';
14
+ export { default as searchRoutes } from './routes/auto/search.routes.js';
15
+ export { insertEngine } from './lib/engine/rest/insert.js';
16
+ export { InsertTableBody, InsertTableResponse } from './lib/schema/insert.js';
17
+ export { default as insertRoutes } from './routes/auto/insert.routes.js';
18
+ export { getEngine } from './lib/engine/rest/get.js';
19
+ export { default as getRoutes } from './routes/auto/get.routes.js';
20
+ export { deleteEngine } from './lib/engine/rest/delete.js';
21
+ export { default as deleteRoutes } from './routes/auto/delete.routes.js';
22
+ export { updateEngine } from './lib/engine/rest/update.js';
23
+ export { UpdateTableBody, UpdateTableResponse } from './lib/schema/update.js';
24
+ export { default as updateRoutes } from './routes/auto/update.routes.js';
25
+ export { bulkUpsertEngine } from './lib/engine/bulk/bulk-upsert.js';
26
+ export { BulkUpsertTableBody, BulkUpsertTableResponse } from './lib/schema/bulk-upsert.js';
27
+ export { default as bulkUpsertRoutes } from './routes/auto/bulk-upsert.routes.js';
28
+ export { bulkDeleteEngine } from './lib/engine/bulk/bulk-delete.js';
29
+ export { BulkDeleteTableBody, BulkDeleteTableResponse } from './lib/schema/bulk-delete.js';
30
+ export { default as bulkDeleteRoutes } from './routes/auto/bulk-delete.routes.js';
31
+ export { Type, type Static } from '@sinclair/typebox';
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, } from './types.js';
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ // Re-export utilities
2
+ export { toCamelCase, toUnderscore, toSchemaName, camelcaseObject, snakecaseRecord, } from './lib/naming.js';
3
+ // DB
4
+ export { QueryClient, createQueryClient, escapeIdent } from './lib/db.js';
5
+ // Dialect
6
+ export { getDialect } from './lib/dialect.js';
7
+ // Adapters
8
+ export { pgQueryable } from './lib/adapters/pg-adapter.js';
9
+ export { mysqlQueryable } from './lib/adapters/mysql-adapter.js';
10
+ // Table helpers
11
+ export { exportTableInfo, defineTable, buildRelation, buildUpsertRule, buildUpsertRules } from './lib/table-helpers.js';
12
+ // Tenant
13
+ export { resolveTenant } from './lib/tenant.js';
14
+ // SqlApi — programmatic high-level API
15
+ export { SqlApi, createSqlApi } from './lib/sql-api.js';
16
+ // Plugin
17
+ export { default as fastifyAutoSqlApi } from './routes/auto/plugin.js';
18
+ // Swagger
19
+ export { setupSwagger } from './lib/setup-swagger.js';
20
+ // Search
21
+ export { searchEngine } from './lib/engine/search/search.js';
22
+ export { SearchTableBodyPost, SearchTableQueryString, SearchTableResponse } from './lib/schema/search.js';
23
+ export { default as searchRoutes } from './routes/auto/search.routes.js';
24
+ // Insert
25
+ export { insertEngine } from './lib/engine/rest/insert.js';
26
+ export { InsertTableBody, InsertTableResponse } from './lib/schema/insert.js';
27
+ export { default as insertRoutes } from './routes/auto/insert.routes.js';
28
+ // Get
29
+ export { getEngine } from './lib/engine/rest/get.js';
30
+ export { default as getRoutes } from './routes/auto/get.routes.js';
31
+ // Delete
32
+ export { deleteEngine } from './lib/engine/rest/delete.js';
33
+ export { default as deleteRoutes } from './routes/auto/delete.routes.js';
34
+ // Update
35
+ export { updateEngine } from './lib/engine/rest/update.js';
36
+ export { UpdateTableBody, UpdateTableResponse } from './lib/schema/update.js';
37
+ export { default as updateRoutes } from './routes/auto/update.routes.js';
38
+ // Bulk Upsert
39
+ export { bulkUpsertEngine } from './lib/engine/bulk/bulk-upsert.js';
40
+ export { BulkUpsertTableBody, BulkUpsertTableResponse } from './lib/schema/bulk-upsert.js';
41
+ export { default as bulkUpsertRoutes } from './routes/auto/bulk-upsert.routes.js';
42
+ // Bulk Delete
43
+ export { bulkDeleteEngine } from './lib/engine/bulk/bulk-delete.js';
44
+ export { BulkDeleteTableBody, BulkDeleteTableResponse } from './lib/schema/bulk-delete.js';
45
+ export { default as bulkDeleteRoutes } from './routes/auto/bulk-delete.routes.js';
46
+ // Re-export deps
47
+ export { Type } from '@sinclair/typebox';
48
+ export { ConditionBuilder, Expression } from 'node-condition-builder';
@@ -0,0 +1,9 @@
1
+ import type { Queryable } from '../../types.js';
2
+ export interface MysqlQueryable {
3
+ query<T = Record<string, unknown>>(sql: string, values?: unknown[]): Promise<[T[] & {
4
+ affectedRows?: number;
5
+ insertId?: number;
6
+ }, unknown]>;
7
+ }
8
+ export declare function mysqlQueryable(pool: MysqlQueryable): Queryable;
9
+ //# sourceMappingURL=mysql-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql-adapter.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/mysql-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,gBAAgB,CAAC;AAE3D,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CAyB9D"}
@@ -0,0 +1,21 @@
1
+ export function mysqlQueryable(pool) {
2
+ return {
3
+ async query(text, values) {
4
+ const [result] = await pool.query(text, values);
5
+ // SELECT returns an array of rows
6
+ if (Array.isArray(result) && !('affectedRows' in result)) {
7
+ return {
8
+ rows: result,
9
+ affectedRows: result.length,
10
+ };
11
+ }
12
+ // INSERT/UPDATE/DELETE returns ResultSetHeader-like
13
+ const header = result;
14
+ return {
15
+ rows: [],
16
+ affectedRows: header.affectedRows ?? 0,
17
+ insertId: header.insertId,
18
+ };
19
+ },
20
+ };
21
+ }
@@ -0,0 +1,9 @@
1
+ import type { Queryable } from '../../types.js';
2
+ export interface PgQueryable {
3
+ query<T = Record<string, unknown>>(text: string, values?: unknown[]): Promise<{
4
+ rows: T[];
5
+ rowCount: number | null;
6
+ }>;
7
+ }
8
+ export declare function pgQueryable(client: PgQueryable): Queryable;
9
+ //# sourceMappingURL=pg-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-adapter.d.ts","sourceRoot":"","sources":["../../../src/lib/adapters/pg-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,gBAAgB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAa1D"}
@@ -0,0 +1,11 @@
1
+ export function pgQueryable(client) {
2
+ return {
3
+ async query(text, values) {
4
+ const result = await client.query(text, values);
5
+ return {
6
+ rows: result.rows,
7
+ affectedRows: result.rowCount ?? 0,
8
+ };
9
+ },
10
+ };
11
+ }
@@ -0,0 +1,3 @@
1
+ import type { SqlApiConfig } from '../../types.js';
2
+ export declare function loadConfig(): Promise<SqlApiConfig>;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAOnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAyBxD"}
@@ -0,0 +1,29 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ import { resolve } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ const DEFAULTS = {
5
+ outputDir: './src/db',
6
+ schema: 'public',
7
+ };
8
+ export async function loadConfig() {
9
+ const candidates = ['sqlapi.config.ts', 'sqlapi.config.mjs', 'sqlapi.config.js'];
10
+ const configPath = candidates
11
+ .map((f) => resolve(process.cwd(), f))
12
+ .find((p) => existsSync(p)) ?? null;
13
+ if (!configPath) {
14
+ return { ...DEFAULTS };
15
+ }
16
+ try {
17
+ const configUrl = pathToFileURL(configPath).href;
18
+ const mod = await import(configUrl);
19
+ const userConfig = mod.default ?? mod;
20
+ return {
21
+ ...DEFAULTS,
22
+ ...userConfig,
23
+ };
24
+ }
25
+ catch (err) {
26
+ console.warn(`Warning: failed to load ${configPath}, using defaults. Error: ${err.message}`);
27
+ return { ...DEFAULTS };
28
+ }
29
+ }
@@ -0,0 +1,16 @@
1
+ import type { ColumnInfo } from '../../types.js';
2
+ export declare function buildMysqlConnectionConfig(): {
3
+ host: string;
4
+ port: number;
5
+ user: string;
6
+ password: string;
7
+ database: string;
8
+ };
9
+ export declare function introspectMysqlTables(connectionConfig: {
10
+ host: string;
11
+ port: number;
12
+ user: string;
13
+ password: string;
14
+ database: string;
15
+ }, schema: string): Promise<ColumnInfo[]>;
16
+ //# sourceMappingURL=mysql-introspect.d.ts.map
@@ -0,0 +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,CAiCvB"}
@@ -0,0 +1,98 @@
1
+ import { createRequire } from 'node:module';
2
+ export function buildMysqlConnectionConfig() {
3
+ if (process.env.DATABASE_URL) {
4
+ const url = new URL(process.env.DATABASE_URL);
5
+ return {
6
+ host: url.hostname,
7
+ port: parseInt(url.port || '3306', 10),
8
+ user: url.username,
9
+ password: url.password,
10
+ database: url.pathname.replace('/', ''),
11
+ };
12
+ }
13
+ return {
14
+ host: process.env.MYSQL_HOST || '127.0.0.1',
15
+ port: parseInt(process.env.MYSQL_PORT || '3306', 10),
16
+ user: process.env.MYSQL_USER || 'test',
17
+ password: process.env.MYSQL_PASSWORD || 'test',
18
+ database: process.env.MYSQL_DB || 'testdb',
19
+ };
20
+ }
21
+ // Map MySQL DATA_TYPE to equivalent PG udt_name for schema-codegen compatibility
22
+ function mapMysqlType(dataType) {
23
+ switch (dataType.toLowerCase()) {
24
+ case 'int':
25
+ case 'mediumint':
26
+ return 'int4';
27
+ case 'smallint':
28
+ case 'tinyint':
29
+ return 'int2';
30
+ case 'bigint':
31
+ return 'int8';
32
+ case 'decimal':
33
+ case 'double':
34
+ case 'float':
35
+ return 'numeric';
36
+ case 'varchar':
37
+ return 'varchar';
38
+ case 'char':
39
+ return 'char';
40
+ case 'text':
41
+ case 'mediumtext':
42
+ case 'longtext':
43
+ case 'tinytext':
44
+ return 'text';
45
+ case 'datetime':
46
+ case 'timestamp':
47
+ return 'timestamp';
48
+ case 'date':
49
+ return 'date';
50
+ case 'time':
51
+ return 'time';
52
+ case 'json':
53
+ return 'json';
54
+ case 'boolean':
55
+ case 'bool':
56
+ return 'bool';
57
+ case 'enum':
58
+ return 'varchar';
59
+ case 'blob':
60
+ case 'mediumblob':
61
+ case 'longblob':
62
+ case 'tinyblob':
63
+ return 'text';
64
+ default:
65
+ return 'varchar';
66
+ }
67
+ }
68
+ export async function introspectMysqlTables(connectionConfig, schema) {
69
+ // Dynamic import: mysql2 is optional peer dependency.
70
+ // Use createRequire from cwd so it works with npm link.
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ let mysql2;
73
+ try {
74
+ const require = createRequire(process.cwd() + '/noop.js');
75
+ mysql2 = require('mysql2/promise');
76
+ }
77
+ catch {
78
+ throw new Error('mysql2 is required for MySQL/MariaDB introspection. Install it with: npm install mysql2');
79
+ }
80
+ const connection = await mysql2.createConnection(connectionConfig);
81
+ try {
82
+ const [rows] = await connection.query(`SELECT table_name, column_name, data_type, column_default, is_nullable
83
+ FROM information_schema.columns
84
+ WHERE table_schema = ?
85
+ ORDER BY table_name, ordinal_position`, [schema]);
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ return rows.map((row) => ({
88
+ table_name: row.TABLE_NAME || row.table_name,
89
+ column_name: row.COLUMN_NAME || row.column_name,
90
+ udt_name: mapMysqlType(row.DATA_TYPE || row.data_type),
91
+ column_default: row.COLUMN_DEFAULT || row.column_default,
92
+ is_nullable: row.IS_NULLABLE || row.is_nullable,
93
+ }));
94
+ }
95
+ finally {
96
+ await connection.end();
97
+ }
98
+ }
@@ -0,0 +1,4 @@
1
+ import type { ColumnInfo } from '../../types.js';
2
+ export declare function buildConnectionString(): string;
3
+ export declare function introspectTables(connectionString: string, schema: string): Promise<ColumnInfo[]>;
4
+ //# sourceMappingURL=pg-introspect.d.ts.map
@@ -0,0 +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,CA4BvB"}
@@ -0,0 +1,36 @@
1
+ import { createRequire } from 'node:module';
2
+ export function buildConnectionString() {
3
+ if (process.env.DATABASE_URL) {
4
+ return process.env.DATABASE_URL;
5
+ }
6
+ const host = process.env.POSTGRES_HOST || '127.0.0.1';
7
+ const port = process.env.POSTGRES_PORT || '5433';
8
+ const user = process.env.POSTGRES_USER || 'test';
9
+ const password = process.env.POSTGRES_PASSWORD || 'test';
10
+ const db = process.env.POSTGRES_DB || 'testdb';
11
+ return `postgres://${user}:${password}@${host}:${port}/${db}`;
12
+ }
13
+ export async function introspectTables(connectionString, schema) {
14
+ // Dynamic require from cwd so it works with npm link
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ let pg;
17
+ try {
18
+ const require = createRequire(process.cwd() + '/noop.js');
19
+ pg = require('pg');
20
+ }
21
+ catch {
22
+ throw new Error('pg is required for PostgreSQL introspection. Install it with: npm install pg');
23
+ }
24
+ const client = new pg.Client({ connectionString });
25
+ try {
26
+ await client.connect();
27
+ const result = await client.query(`SELECT table_name, column_name, udt_name, column_default, is_nullable
28
+ FROM information_schema.columns
29
+ WHERE table_schema = $1
30
+ ORDER BY table_name, ordinal_position`, [schema]);
31
+ return result.rows;
32
+ }
33
+ finally {
34
+ await client.end();
35
+ }
36
+ }
@@ -0,0 +1,8 @@
1
+ import type { ColumnInfo, TableMap } from '../../types.js';
2
+ export declare function convertColType(udtName: string, columnInfo: {
3
+ column_default: string | null;
4
+ is_nullable: string;
5
+ }): string;
6
+ export declare function buildTableMap(rows: ColumnInfo[]): TableMap;
7
+ export declare function generateSchemaFile(schemaName: string, tableName: string, fields: Record<string, string>): string;
8
+ //# sourceMappingURL=schema-codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-codegen.d.ts","sourceRoot":"","sources":["../../../src/lib/cli/schema-codegen.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE3D,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE;IAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACjE,MAAM,CAoDR;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,QAAQ,CAkB1D;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,MAAM,CAsCR"}