postgresdk 0.10.0 → 0.10.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/LICENSE +21 -0
- package/README.md +38 -1
- package/dist/cli.js +337 -117
- package/dist/index.js +337 -117
- package/package.json +11 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 postgresdk contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -178,9 +178,46 @@ const filtered = await sdk.users.list({
|
|
|
178
178
|
deleted_at: { $is: null } // NULL checks
|
|
179
179
|
}
|
|
180
180
|
});
|
|
181
|
+
|
|
182
|
+
// OR logic - match any condition
|
|
183
|
+
const results = await sdk.users.list({
|
|
184
|
+
where: {
|
|
185
|
+
$or: [
|
|
186
|
+
{ email: { $ilike: '%@gmail.com' } },
|
|
187
|
+
{ email: { $ilike: '%@yahoo.com' } },
|
|
188
|
+
{ status: 'premium' }
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Complex queries with AND/OR
|
|
194
|
+
const complex = await sdk.users.list({
|
|
195
|
+
where: {
|
|
196
|
+
status: 'active', // Implicit AND at root level
|
|
197
|
+
$or: [
|
|
198
|
+
{ age: { $lt: 18 } },
|
|
199
|
+
{ age: { $gt: 65 } }
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Nested logic (2 levels)
|
|
205
|
+
const nested = await sdk.users.list({
|
|
206
|
+
where: {
|
|
207
|
+
$and: [
|
|
208
|
+
{
|
|
209
|
+
$or: [
|
|
210
|
+
{ firstName: { $ilike: '%john%' } },
|
|
211
|
+
{ lastName: { $ilike: '%john%' } }
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
{ status: 'active' }
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
});
|
|
181
218
|
```
|
|
182
219
|
|
|
183
|
-
See the generated SDK documentation for all available operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$like`, `$ilike`, `$is`, `$isNot`.
|
|
220
|
+
See the generated SDK documentation for all available operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$like`, `$ilike`, `$is`, `$isNot`, `$or`, `$and`.
|
|
184
221
|
|
|
185
222
|
## Authentication
|
|
186
223
|
|
package/dist/cli.js
CHANGED
|
@@ -1302,6 +1302,53 @@ function generateUnifiedContractMarkdown(contract) {
|
|
|
1302
1302
|
lines.push("| `$is` | IS NULL | `{ deleted_at: { $is: null } }` | Nullable fields |");
|
|
1303
1303
|
lines.push("| `$isNot` | IS NOT NULL | `{ created_by: { $isNot: null } }` | Nullable fields |");
|
|
1304
1304
|
lines.push("");
|
|
1305
|
+
lines.push("### Logical Operators");
|
|
1306
|
+
lines.push("");
|
|
1307
|
+
lines.push("Combine conditions using `$or` and `$and` (supports 2 levels of nesting):");
|
|
1308
|
+
lines.push("");
|
|
1309
|
+
lines.push("| Operator | Description | Example |");
|
|
1310
|
+
lines.push("|----------|-------------|---------|");
|
|
1311
|
+
lines.push("| `$or` | Match any condition | `{ $or: [{ status: 'active' }, { role: 'admin' }] }` |");
|
|
1312
|
+
lines.push("| `$and` | Match all conditions (explicit) | `{ $and: [{ age: { $gte: 18 } }, { status: 'verified' }] }` |");
|
|
1313
|
+
lines.push("");
|
|
1314
|
+
lines.push("```typescript");
|
|
1315
|
+
lines.push("// OR - match any condition");
|
|
1316
|
+
lines.push("const results = await sdk.users.list({");
|
|
1317
|
+
lines.push(" where: {");
|
|
1318
|
+
lines.push(" $or: [");
|
|
1319
|
+
lines.push(" { email: { $ilike: '%@gmail.com' } },");
|
|
1320
|
+
lines.push(" { status: 'premium' }");
|
|
1321
|
+
lines.push(" ]");
|
|
1322
|
+
lines.push(" }");
|
|
1323
|
+
lines.push("});");
|
|
1324
|
+
lines.push("");
|
|
1325
|
+
lines.push("// Mixed AND + OR (implicit AND at root level)");
|
|
1326
|
+
lines.push("const complex = await sdk.users.list({");
|
|
1327
|
+
lines.push(" where: {");
|
|
1328
|
+
lines.push(" status: 'active', // AND");
|
|
1329
|
+
lines.push(" $or: [");
|
|
1330
|
+
lines.push(" { age: { $lt: 18 } },");
|
|
1331
|
+
lines.push(" { age: { $gt: 65 } }");
|
|
1332
|
+
lines.push(" ]");
|
|
1333
|
+
lines.push(" }");
|
|
1334
|
+
lines.push("});");
|
|
1335
|
+
lines.push("");
|
|
1336
|
+
lines.push("// Nested (2 levels max)");
|
|
1337
|
+
lines.push("const nested = await sdk.users.list({");
|
|
1338
|
+
lines.push(" where: {");
|
|
1339
|
+
lines.push(" $and: [");
|
|
1340
|
+
lines.push(" {");
|
|
1341
|
+
lines.push(" $or: [");
|
|
1342
|
+
lines.push(" { firstName: { $ilike: '%john%' } },");
|
|
1343
|
+
lines.push(" { lastName: { $ilike: '%john%' } }");
|
|
1344
|
+
lines.push(" ]");
|
|
1345
|
+
lines.push(" },");
|
|
1346
|
+
lines.push(" { status: 'active' }");
|
|
1347
|
+
lines.push(" ]");
|
|
1348
|
+
lines.push(" }");
|
|
1349
|
+
lines.push("});");
|
|
1350
|
+
lines.push("```");
|
|
1351
|
+
lines.push("");
|
|
1305
1352
|
lines.push("**Note:** The WHERE clause types are fully type-safe. TypeScript will only allow operators that are valid for each field type.");
|
|
1306
1353
|
lines.push("");
|
|
1307
1354
|
lines.push("## Resources");
|
|
@@ -2387,7 +2434,14 @@ function buildGraph(model) {
|
|
|
2387
2434
|
|
|
2388
2435
|
// src/emit-include-spec.ts
|
|
2389
2436
|
function emitIncludeSpec(graph) {
|
|
2390
|
-
let out =
|
|
2437
|
+
let out = `/**
|
|
2438
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2439
|
+
*
|
|
2440
|
+
* This file was automatically generated by PostgreSDK.
|
|
2441
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2442
|
+
*
|
|
2443
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2444
|
+
*/
|
|
2391
2445
|
`;
|
|
2392
2446
|
const tables = Object.keys(graph);
|
|
2393
2447
|
for (const table of tables) {
|
|
@@ -2416,7 +2470,14 @@ function toPascal(s) {
|
|
|
2416
2470
|
|
|
2417
2471
|
// src/emit-include-builder.ts
|
|
2418
2472
|
function emitIncludeBuilder(graph, maxDepth) {
|
|
2419
|
-
return
|
|
2473
|
+
return `/**
|
|
2474
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2475
|
+
*
|
|
2476
|
+
* This file was automatically generated by PostgreSDK.
|
|
2477
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2478
|
+
*
|
|
2479
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2480
|
+
*/
|
|
2420
2481
|
export const RELATION_GRAPH = ${JSON.stringify(graph, null, 2)} as const;
|
|
2421
2482
|
type TableName = keyof typeof RELATION_GRAPH;
|
|
2422
2483
|
|
|
@@ -2564,7 +2625,14 @@ function emitHonoRoutes(table, _graph, opts) {
|
|
|
2564
2625
|
const hasAuth = opts.authStrategy && opts.authStrategy !== "none";
|
|
2565
2626
|
const ext = opts.useJsExtensions ? ".js" : "";
|
|
2566
2627
|
const authImport = hasAuth ? `import { authMiddleware } from "../auth${ext}";` : "";
|
|
2567
|
-
return
|
|
2628
|
+
return `/**
|
|
2629
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2630
|
+
*
|
|
2631
|
+
* This file was automatically generated by PostgreSDK.
|
|
2632
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2633
|
+
*
|
|
2634
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2635
|
+
*/
|
|
2568
2636
|
import { Hono } from "hono";
|
|
2569
2637
|
import { z } from "zod";
|
|
2570
2638
|
import { Insert${Type}Schema, Update${Type}Schema } from "../zod/${fileTableName}${ext}";
|
|
@@ -2766,7 +2834,14 @@ function emitClient(table, graph, opts, model) {
|
|
|
2766
2834
|
`;
|
|
2767
2835
|
}
|
|
2768
2836
|
}
|
|
2769
|
-
return
|
|
2837
|
+
return `/**
|
|
2838
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2839
|
+
*
|
|
2840
|
+
* This file was automatically generated by PostgreSDK.
|
|
2841
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2842
|
+
*
|
|
2843
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2844
|
+
*/
|
|
2770
2845
|
import { BaseClient } from "./base-client${ext}";
|
|
2771
2846
|
import type { Where } from "./where-types${ext}";
|
|
2772
2847
|
${typeImports}
|
|
@@ -2813,7 +2888,14 @@ ${includeMethodsCode}}
|
|
|
2813
2888
|
}
|
|
2814
2889
|
function emitClientIndex(tables, useJsExtensions) {
|
|
2815
2890
|
const ext = useJsExtensions ? ".js" : "";
|
|
2816
|
-
let out =
|
|
2891
|
+
let out = `/**
|
|
2892
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2893
|
+
*
|
|
2894
|
+
* This file was automatically generated by PostgreSDK.
|
|
2895
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2896
|
+
*
|
|
2897
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2898
|
+
*/
|
|
2817
2899
|
`;
|
|
2818
2900
|
out += `import { BaseClient, type AuthConfig } from "./base-client${ext}";
|
|
2819
2901
|
`;
|
|
@@ -2886,7 +2968,14 @@ export type { AuthConfig, HeaderMap, AuthHeadersProvider } from "./base-client${
|
|
|
2886
2968
|
|
|
2887
2969
|
// src/emit-base-client.ts
|
|
2888
2970
|
function emitBaseClient() {
|
|
2889
|
-
return
|
|
2971
|
+
return `/**
|
|
2972
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2973
|
+
*
|
|
2974
|
+
* This file was automatically generated by PostgreSDK.
|
|
2975
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2976
|
+
*
|
|
2977
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2978
|
+
*/
|
|
2890
2979
|
|
|
2891
2980
|
export type HeaderMap = Record<string, string>;
|
|
2892
2981
|
export type AuthHeadersProvider = () => Promise<HeaderMap> | HeaderMap;
|
|
@@ -3033,7 +3122,14 @@ function emitIncludeLoader(graph, model, maxDepth, useJsExtensions) {
|
|
|
3033
3122
|
fkIndex[t.name] = t.fks.map((f) => ({ from: f.from, toTable: f.toTable, to: f.to }));
|
|
3034
3123
|
}
|
|
3035
3124
|
const ext = useJsExtensions ? ".js" : "";
|
|
3036
|
-
return
|
|
3125
|
+
return `/**
|
|
3126
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3127
|
+
*
|
|
3128
|
+
* This file was automatically generated by PostgreSDK.
|
|
3129
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3130
|
+
*
|
|
3131
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3132
|
+
*/
|
|
3037
3133
|
import { RELATION_GRAPH } from "./include-builder${ext}";
|
|
3038
3134
|
|
|
3039
3135
|
// Minimal types to keep the file self-contained
|
|
@@ -3354,7 +3450,14 @@ function emitTypes(table, opts) {
|
|
|
3354
3450
|
return ` ${col.name}: ${valueType};`;
|
|
3355
3451
|
}).join(`
|
|
3356
3452
|
`);
|
|
3357
|
-
return
|
|
3453
|
+
return `/**
|
|
3454
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3455
|
+
*
|
|
3456
|
+
* This file was automatically generated by PostgreSDK.
|
|
3457
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3458
|
+
*
|
|
3459
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3460
|
+
*/
|
|
3358
3461
|
export type Insert${Type} = {
|
|
3359
3462
|
${insertFields}
|
|
3360
3463
|
};
|
|
@@ -3369,7 +3472,14 @@ ${selectFields}
|
|
|
3369
3472
|
|
|
3370
3473
|
// src/emit-logger.ts
|
|
3371
3474
|
function emitLogger() {
|
|
3372
|
-
return
|
|
3475
|
+
return `/**
|
|
3476
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3477
|
+
*
|
|
3478
|
+
* This file was automatically generated by PostgreSDK.
|
|
3479
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3480
|
+
*
|
|
3481
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3482
|
+
*/
|
|
3373
3483
|
const DEBUG = process.env.SDK_DEBUG === "1" || process.env.SDK_DEBUG === "true";
|
|
3374
3484
|
|
|
3375
3485
|
export const logger = {
|
|
@@ -3404,7 +3514,14 @@ export function safe<T extends (c: any) => any>(handler: T) {
|
|
|
3404
3514
|
|
|
3405
3515
|
// src/emit-where-types.ts
|
|
3406
3516
|
function emitWhereTypes() {
|
|
3407
|
-
return
|
|
3517
|
+
return `/**
|
|
3518
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3519
|
+
*
|
|
3520
|
+
* This file was automatically generated by PostgreSDK.
|
|
3521
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3522
|
+
*
|
|
3523
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3524
|
+
*/
|
|
3408
3525
|
|
|
3409
3526
|
/**
|
|
3410
3527
|
* WHERE clause operators for filtering
|
|
@@ -3442,11 +3559,26 @@ export type WhereOperator<T> = {
|
|
|
3442
3559
|
export type WhereCondition<T> = T | WhereOperator<T>;
|
|
3443
3560
|
|
|
3444
3561
|
/**
|
|
3445
|
-
* WHERE
|
|
3562
|
+
* Field-level WHERE conditions (without logical operators)
|
|
3446
3563
|
*/
|
|
3447
|
-
export type
|
|
3564
|
+
export type WhereFieldConditions<T> = {
|
|
3448
3565
|
[K in keyof T]?: WhereCondition<T[K]>;
|
|
3449
3566
|
};
|
|
3567
|
+
|
|
3568
|
+
/**
|
|
3569
|
+
* WHERE clause type with support for $or/$and logical operators (2 levels max)
|
|
3570
|
+
*
|
|
3571
|
+
* Examples:
|
|
3572
|
+
* - Basic OR: { $or: [{ name: 'Alice' }, { name: 'Bob' }] }
|
|
3573
|
+
* - Mixed AND + OR: { status: 'active', $or: [{ age: { $gt: 65 } }, { age: { $lt: 18 } }] }
|
|
3574
|
+
* - Nested (2 levels): { $and: [{ $or: [{ name: 'Alice' }, { name: 'Bob' }] }, { status: 'active' }] }
|
|
3575
|
+
*/
|
|
3576
|
+
export type Where<T> = WhereFieldConditions<T> & {
|
|
3577
|
+
/** OR - at least one condition must be true */
|
|
3578
|
+
$or?: (WhereFieldConditions<T>)[];
|
|
3579
|
+
/** AND - all conditions must be true (alternative to implicit root-level AND) */
|
|
3580
|
+
$and?: (WhereFieldConditions<T> | { $or?: WhereFieldConditions<T>[] })[];
|
|
3581
|
+
};
|
|
3450
3582
|
`;
|
|
3451
3583
|
}
|
|
3452
3584
|
|
|
@@ -3464,7 +3596,14 @@ function emitAuth(cfgAuth) {
|
|
|
3464
3596
|
const JWT_SHARED_SECRET = JSON.stringify(jwtShared);
|
|
3465
3597
|
const JWT_ISSUER = jwtIssuer === undefined ? "undefined" : JSON.stringify(jwtIssuer);
|
|
3466
3598
|
const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
|
|
3467
|
-
return
|
|
3599
|
+
return `/**
|
|
3600
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3601
|
+
*
|
|
3602
|
+
* This file was automatically generated by PostgreSDK.
|
|
3603
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3604
|
+
*
|
|
3605
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3606
|
+
*/
|
|
3468
3607
|
import type { Context, Next } from "hono";
|
|
3469
3608
|
|
|
3470
3609
|
// ---- Config inlined by generator ----
|
|
@@ -3621,7 +3760,14 @@ function emitHonoRouter(tables, hasAuth, useJsExtensions) {
|
|
|
3621
3760
|
return `export { register${Type}Routes } from "./routes/${name}${ext}";`;
|
|
3622
3761
|
}).join(`
|
|
3623
3762
|
`);
|
|
3624
|
-
return
|
|
3763
|
+
return `/**
|
|
3764
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3765
|
+
*
|
|
3766
|
+
* This file was automatically generated by PostgreSDK.
|
|
3767
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3768
|
+
*
|
|
3769
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3770
|
+
*/
|
|
3625
3771
|
import { Hono } from "hono";
|
|
3626
3772
|
import { SDK_MANIFEST } from "./sdk-bundle${ext}";
|
|
3627
3773
|
import { getContract } from "./contract${ext}";
|
|
@@ -3755,7 +3901,14 @@ function emitSdkBundle(clientFiles, clientDir) {
|
|
|
3755
3901
|
}
|
|
3756
3902
|
const version = `1.0.0`;
|
|
3757
3903
|
const generated = new Date().toISOString();
|
|
3758
|
-
return
|
|
3904
|
+
return `/**
|
|
3905
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3906
|
+
*
|
|
3907
|
+
* This file was automatically generated by PostgreSDK.
|
|
3908
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3909
|
+
*
|
|
3910
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3911
|
+
*/
|
|
3759
3912
|
|
|
3760
3913
|
export const SDK_MANIFEST = {
|
|
3761
3914
|
version: "${version}",
|
|
@@ -3859,6 +4012,155 @@ export async function getByPk(
|
|
|
3859
4012
|
}
|
|
3860
4013
|
}
|
|
3861
4014
|
|
|
4015
|
+
/**
|
|
4016
|
+
* Build WHERE clause recursively, supporting $or/$and operators
|
|
4017
|
+
* Returns { sql: string, params: any[], nextParamIndex: number }
|
|
4018
|
+
*/
|
|
4019
|
+
function buildWhereClause(
|
|
4020
|
+
whereClause: any,
|
|
4021
|
+
startParamIndex: number
|
|
4022
|
+
): { sql: string; params: any[]; nextParamIndex: number } {
|
|
4023
|
+
const whereParts: string[] = [];
|
|
4024
|
+
const whereParams: any[] = [];
|
|
4025
|
+
let paramIndex = startParamIndex;
|
|
4026
|
+
|
|
4027
|
+
if (!whereClause || typeof whereClause !== 'object') {
|
|
4028
|
+
return { sql: '', params: [], nextParamIndex: paramIndex };
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
// Separate logical operators from field conditions
|
|
4032
|
+
const { $or, $and, ...fieldConditions } = whereClause;
|
|
4033
|
+
|
|
4034
|
+
// Process field-level conditions
|
|
4035
|
+
for (const [key, value] of Object.entries(fieldConditions)) {
|
|
4036
|
+
if (value === undefined) {
|
|
4037
|
+
continue;
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
// Handle operator objects like { $gt: 5, $like: "%test%" }
|
|
4041
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
4042
|
+
for (const [op, opValue] of Object.entries(value)) {
|
|
4043
|
+
if (opValue === undefined) continue;
|
|
4044
|
+
|
|
4045
|
+
switch (op) {
|
|
4046
|
+
case '$eq':
|
|
4047
|
+
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
4048
|
+
whereParams.push(opValue);
|
|
4049
|
+
paramIndex++;
|
|
4050
|
+
break;
|
|
4051
|
+
case '$ne':
|
|
4052
|
+
whereParts.push(\`"\${key}" != $\${paramIndex}\`);
|
|
4053
|
+
whereParams.push(opValue);
|
|
4054
|
+
paramIndex++;
|
|
4055
|
+
break;
|
|
4056
|
+
case '$gt':
|
|
4057
|
+
whereParts.push(\`"\${key}" > $\${paramIndex}\`);
|
|
4058
|
+
whereParams.push(opValue);
|
|
4059
|
+
paramIndex++;
|
|
4060
|
+
break;
|
|
4061
|
+
case '$gte':
|
|
4062
|
+
whereParts.push(\`"\${key}" >= $\${paramIndex}\`);
|
|
4063
|
+
whereParams.push(opValue);
|
|
4064
|
+
paramIndex++;
|
|
4065
|
+
break;
|
|
4066
|
+
case '$lt':
|
|
4067
|
+
whereParts.push(\`"\${key}" < $\${paramIndex}\`);
|
|
4068
|
+
whereParams.push(opValue);
|
|
4069
|
+
paramIndex++;
|
|
4070
|
+
break;
|
|
4071
|
+
case '$lte':
|
|
4072
|
+
whereParts.push(\`"\${key}" <= $\${paramIndex}\`);
|
|
4073
|
+
whereParams.push(opValue);
|
|
4074
|
+
paramIndex++;
|
|
4075
|
+
break;
|
|
4076
|
+
case '$in':
|
|
4077
|
+
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
4078
|
+
whereParts.push(\`"\${key}" = ANY($\${paramIndex})\`);
|
|
4079
|
+
whereParams.push(opValue);
|
|
4080
|
+
paramIndex++;
|
|
4081
|
+
}
|
|
4082
|
+
break;
|
|
4083
|
+
case '$nin':
|
|
4084
|
+
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
4085
|
+
whereParts.push(\`"\${key}" != ALL($\${paramIndex})\`);
|
|
4086
|
+
whereParams.push(opValue);
|
|
4087
|
+
paramIndex++;
|
|
4088
|
+
}
|
|
4089
|
+
break;
|
|
4090
|
+
case '$like':
|
|
4091
|
+
whereParts.push(\`"\${key}" LIKE $\${paramIndex}\`);
|
|
4092
|
+
whereParams.push(opValue);
|
|
4093
|
+
paramIndex++;
|
|
4094
|
+
break;
|
|
4095
|
+
case '$ilike':
|
|
4096
|
+
whereParts.push(\`"\${key}" ILIKE $\${paramIndex}\`);
|
|
4097
|
+
whereParams.push(opValue);
|
|
4098
|
+
paramIndex++;
|
|
4099
|
+
break;
|
|
4100
|
+
case '$is':
|
|
4101
|
+
if (opValue === null) {
|
|
4102
|
+
whereParts.push(\`"\${key}" IS NULL\`);
|
|
4103
|
+
}
|
|
4104
|
+
break;
|
|
4105
|
+
case '$isNot':
|
|
4106
|
+
if (opValue === null) {
|
|
4107
|
+
whereParts.push(\`"\${key}" IS NOT NULL\`);
|
|
4108
|
+
}
|
|
4109
|
+
break;
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
} else if (value === null) {
|
|
4113
|
+
// Direct null value
|
|
4114
|
+
whereParts.push(\`"\${key}" IS NULL\`);
|
|
4115
|
+
} else {
|
|
4116
|
+
// Direct value (simple equality)
|
|
4117
|
+
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
4118
|
+
whereParams.push(value);
|
|
4119
|
+
paramIndex++;
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
|
|
4123
|
+
// Handle $or operator
|
|
4124
|
+
if ($or && Array.isArray($or)) {
|
|
4125
|
+
if ($or.length === 0) {
|
|
4126
|
+
// Empty OR is logically FALSE - matches nothing
|
|
4127
|
+
whereParts.push('FALSE');
|
|
4128
|
+
} else {
|
|
4129
|
+
const orParts: string[] = [];
|
|
4130
|
+
for (const orCondition of $or) {
|
|
4131
|
+
const result = buildWhereClause(orCondition, paramIndex);
|
|
4132
|
+
if (result.sql) {
|
|
4133
|
+
orParts.push(result.sql);
|
|
4134
|
+
whereParams.push(...result.params);
|
|
4135
|
+
paramIndex = result.nextParamIndex;
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
if (orParts.length > 0) {
|
|
4139
|
+
whereParts.push(\`(\${orParts.join(' OR ')})\`);
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
|
|
4144
|
+
// Handle $and operator
|
|
4145
|
+
if ($and && Array.isArray($and) && $and.length > 0) {
|
|
4146
|
+
const andParts: string[] = [];
|
|
4147
|
+
for (const andCondition of $and) {
|
|
4148
|
+
const result = buildWhereClause(andCondition, paramIndex);
|
|
4149
|
+
if (result.sql) {
|
|
4150
|
+
andParts.push(result.sql);
|
|
4151
|
+
whereParams.push(...result.params);
|
|
4152
|
+
paramIndex = result.nextParamIndex;
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
if (andParts.length > 0) {
|
|
4156
|
+
whereParts.push(\`(\${andParts.join(' AND ')})\`);
|
|
4157
|
+
}
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
const sql = whereParts.join(' AND ');
|
|
4161
|
+
return { sql, params: whereParams, nextParamIndex: paramIndex };
|
|
4162
|
+
}
|
|
4163
|
+
|
|
3862
4164
|
/**
|
|
3863
4165
|
* LIST operation - Get multiple records with optional filters
|
|
3864
4166
|
*/
|
|
@@ -3868,136 +4170,54 @@ export async function listRecords(
|
|
|
3868
4170
|
): Promise<{ data?: any; error?: string; issues?: any; needsIncludes?: boolean; includeSpec?: any; status: number }> {
|
|
3869
4171
|
try {
|
|
3870
4172
|
const { where: whereClause, limit = 50, offset = 0, include } = params;
|
|
3871
|
-
|
|
4173
|
+
|
|
3872
4174
|
// Build WHERE clause
|
|
3873
|
-
const whereParts: string[] = [];
|
|
3874
|
-
const whereParams: any[] = [];
|
|
3875
4175
|
let paramIndex = 1;
|
|
3876
|
-
|
|
4176
|
+
const whereParts: string[] = [];
|
|
4177
|
+
let whereParams: any[] = [];
|
|
4178
|
+
|
|
3877
4179
|
// Add soft delete filter if applicable
|
|
3878
4180
|
if (ctx.softDeleteColumn) {
|
|
3879
4181
|
whereParts.push(\`"\${ctx.softDeleteColumn}" IS NULL\`);
|
|
3880
4182
|
}
|
|
3881
|
-
|
|
3882
|
-
// Add user-provided where conditions
|
|
3883
|
-
if (whereClause && typeof whereClause === 'object') {
|
|
3884
|
-
for (const [key, value] of Object.entries(whereClause)) {
|
|
3885
|
-
if (value === undefined) {
|
|
3886
|
-
// Skip undefined values
|
|
3887
|
-
continue;
|
|
3888
|
-
}
|
|
3889
4183
|
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3898
|
-
whereParams.push(opValue);
|
|
3899
|
-
paramIndex++;
|
|
3900
|
-
break;
|
|
3901
|
-
case '$ne':
|
|
3902
|
-
whereParts.push(\`"\${key}" != $\${paramIndex}\`);
|
|
3903
|
-
whereParams.push(opValue);
|
|
3904
|
-
paramIndex++;
|
|
3905
|
-
break;
|
|
3906
|
-
case '$gt':
|
|
3907
|
-
whereParts.push(\`"\${key}" > $\${paramIndex}\`);
|
|
3908
|
-
whereParams.push(opValue);
|
|
3909
|
-
paramIndex++;
|
|
3910
|
-
break;
|
|
3911
|
-
case '$gte':
|
|
3912
|
-
whereParts.push(\`"\${key}" >= $\${paramIndex}\`);
|
|
3913
|
-
whereParams.push(opValue);
|
|
3914
|
-
paramIndex++;
|
|
3915
|
-
break;
|
|
3916
|
-
case '$lt':
|
|
3917
|
-
whereParts.push(\`"\${key}" < $\${paramIndex}\`);
|
|
3918
|
-
whereParams.push(opValue);
|
|
3919
|
-
paramIndex++;
|
|
3920
|
-
break;
|
|
3921
|
-
case '$lte':
|
|
3922
|
-
whereParts.push(\`"\${key}" <= $\${paramIndex}\`);
|
|
3923
|
-
whereParams.push(opValue);
|
|
3924
|
-
paramIndex++;
|
|
3925
|
-
break;
|
|
3926
|
-
case '$in':
|
|
3927
|
-
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3928
|
-
whereParts.push(\`"\${key}" = ANY($\${paramIndex})\`);
|
|
3929
|
-
whereParams.push(opValue);
|
|
3930
|
-
paramIndex++;
|
|
3931
|
-
}
|
|
3932
|
-
break;
|
|
3933
|
-
case '$nin':
|
|
3934
|
-
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3935
|
-
whereParts.push(\`"\${key}" != ALL($\${paramIndex})\`);
|
|
3936
|
-
whereParams.push(opValue);
|
|
3937
|
-
paramIndex++;
|
|
3938
|
-
}
|
|
3939
|
-
break;
|
|
3940
|
-
case '$like':
|
|
3941
|
-
whereParts.push(\`"\${key}" LIKE $\${paramIndex}\`);
|
|
3942
|
-
whereParams.push(opValue);
|
|
3943
|
-
paramIndex++;
|
|
3944
|
-
break;
|
|
3945
|
-
case '$ilike':
|
|
3946
|
-
whereParts.push(\`"\${key}" ILIKE $\${paramIndex}\`);
|
|
3947
|
-
whereParams.push(opValue);
|
|
3948
|
-
paramIndex++;
|
|
3949
|
-
break;
|
|
3950
|
-
case '$is':
|
|
3951
|
-
if (opValue === null) {
|
|
3952
|
-
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3953
|
-
}
|
|
3954
|
-
break;
|
|
3955
|
-
case '$isNot':
|
|
3956
|
-
if (opValue === null) {
|
|
3957
|
-
whereParts.push(\`"\${key}" IS NOT NULL\`);
|
|
3958
|
-
}
|
|
3959
|
-
break;
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
|
-
} else if (value === null) {
|
|
3963
|
-
// Direct null value
|
|
3964
|
-
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3965
|
-
} else {
|
|
3966
|
-
// Direct value (simple equality)
|
|
3967
|
-
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3968
|
-
whereParams.push(value);
|
|
3969
|
-
paramIndex++;
|
|
3970
|
-
}
|
|
4184
|
+
// Add user-provided where conditions
|
|
4185
|
+
if (whereClause) {
|
|
4186
|
+
const result = buildWhereClause(whereClause, paramIndex);
|
|
4187
|
+
if (result.sql) {
|
|
4188
|
+
whereParts.push(result.sql);
|
|
4189
|
+
whereParams = result.params;
|
|
4190
|
+
paramIndex = result.nextParamIndex;
|
|
3971
4191
|
}
|
|
3972
4192
|
}
|
|
3973
|
-
|
|
4193
|
+
|
|
3974
4194
|
const whereSQL = whereParts.length > 0 ? \`WHERE \${whereParts.join(" AND ")}\` : "";
|
|
3975
|
-
|
|
4195
|
+
|
|
3976
4196
|
// Add limit and offset params
|
|
3977
4197
|
const limitParam = \`$\${paramIndex}\`;
|
|
3978
4198
|
const offsetParam = \`$\${paramIndex + 1}\`;
|
|
3979
4199
|
const allParams = [...whereParams, limit, offset];
|
|
3980
|
-
|
|
4200
|
+
|
|
3981
4201
|
const text = \`SELECT * FROM "\${ctx.table}" \${whereSQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
3982
4202
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
3983
|
-
|
|
4203
|
+
|
|
3984
4204
|
const { rows } = await ctx.pg.query(text, allParams);
|
|
3985
|
-
|
|
4205
|
+
|
|
3986
4206
|
if (!include) {
|
|
3987
4207
|
log.debug(\`LIST \${ctx.table} rows:\`, rows.length);
|
|
3988
4208
|
return { data: rows, status: 200 };
|
|
3989
4209
|
}
|
|
3990
|
-
|
|
4210
|
+
|
|
3991
4211
|
// Include logic will be handled by the include-loader
|
|
3992
4212
|
// For now, just return the rows with a note that includes need to be applied
|
|
3993
4213
|
log.debug(\`LIST \${ctx.table} include spec:\`, include);
|
|
3994
4214
|
return { data: rows, needsIncludes: true, includeSpec: include, status: 200 };
|
|
3995
4215
|
} catch (e: any) {
|
|
3996
4216
|
log.error(\`LIST \${ctx.table} error:\`, e?.stack ?? e);
|
|
3997
|
-
return {
|
|
3998
|
-
error: e?.message ?? "Internal error",
|
|
4217
|
+
return {
|
|
4218
|
+
error: e?.message ?? "Internal error",
|
|
3999
4219
|
...(DEBUG ? { stack: e?.stack } : {}),
|
|
4000
|
-
status: 500
|
|
4220
|
+
status: 500
|
|
4001
4221
|
};
|
|
4002
4222
|
}
|
|
4003
4223
|
}
|
package/dist/index.js
CHANGED
|
@@ -1301,6 +1301,53 @@ function generateUnifiedContractMarkdown(contract) {
|
|
|
1301
1301
|
lines.push("| `$is` | IS NULL | `{ deleted_at: { $is: null } }` | Nullable fields |");
|
|
1302
1302
|
lines.push("| `$isNot` | IS NOT NULL | `{ created_by: { $isNot: null } }` | Nullable fields |");
|
|
1303
1303
|
lines.push("");
|
|
1304
|
+
lines.push("### Logical Operators");
|
|
1305
|
+
lines.push("");
|
|
1306
|
+
lines.push("Combine conditions using `$or` and `$and` (supports 2 levels of nesting):");
|
|
1307
|
+
lines.push("");
|
|
1308
|
+
lines.push("| Operator | Description | Example |");
|
|
1309
|
+
lines.push("|----------|-------------|---------|");
|
|
1310
|
+
lines.push("| `$or` | Match any condition | `{ $or: [{ status: 'active' }, { role: 'admin' }] }` |");
|
|
1311
|
+
lines.push("| `$and` | Match all conditions (explicit) | `{ $and: [{ age: { $gte: 18 } }, { status: 'verified' }] }` |");
|
|
1312
|
+
lines.push("");
|
|
1313
|
+
lines.push("```typescript");
|
|
1314
|
+
lines.push("// OR - match any condition");
|
|
1315
|
+
lines.push("const results = await sdk.users.list({");
|
|
1316
|
+
lines.push(" where: {");
|
|
1317
|
+
lines.push(" $or: [");
|
|
1318
|
+
lines.push(" { email: { $ilike: '%@gmail.com' } },");
|
|
1319
|
+
lines.push(" { status: 'premium' }");
|
|
1320
|
+
lines.push(" ]");
|
|
1321
|
+
lines.push(" }");
|
|
1322
|
+
lines.push("});");
|
|
1323
|
+
lines.push("");
|
|
1324
|
+
lines.push("// Mixed AND + OR (implicit AND at root level)");
|
|
1325
|
+
lines.push("const complex = await sdk.users.list({");
|
|
1326
|
+
lines.push(" where: {");
|
|
1327
|
+
lines.push(" status: 'active', // AND");
|
|
1328
|
+
lines.push(" $or: [");
|
|
1329
|
+
lines.push(" { age: { $lt: 18 } },");
|
|
1330
|
+
lines.push(" { age: { $gt: 65 } }");
|
|
1331
|
+
lines.push(" ]");
|
|
1332
|
+
lines.push(" }");
|
|
1333
|
+
lines.push("});");
|
|
1334
|
+
lines.push("");
|
|
1335
|
+
lines.push("// Nested (2 levels max)");
|
|
1336
|
+
lines.push("const nested = await sdk.users.list({");
|
|
1337
|
+
lines.push(" where: {");
|
|
1338
|
+
lines.push(" $and: [");
|
|
1339
|
+
lines.push(" {");
|
|
1340
|
+
lines.push(" $or: [");
|
|
1341
|
+
lines.push(" { firstName: { $ilike: '%john%' } },");
|
|
1342
|
+
lines.push(" { lastName: { $ilike: '%john%' } }");
|
|
1343
|
+
lines.push(" ]");
|
|
1344
|
+
lines.push(" },");
|
|
1345
|
+
lines.push(" { status: 'active' }");
|
|
1346
|
+
lines.push(" ]");
|
|
1347
|
+
lines.push(" }");
|
|
1348
|
+
lines.push("});");
|
|
1349
|
+
lines.push("```");
|
|
1350
|
+
lines.push("");
|
|
1304
1351
|
lines.push("**Note:** The WHERE clause types are fully type-safe. TypeScript will only allow operators that are valid for each field type.");
|
|
1305
1352
|
lines.push("");
|
|
1306
1353
|
lines.push("## Resources");
|
|
@@ -1627,7 +1674,14 @@ function buildGraph(model) {
|
|
|
1627
1674
|
|
|
1628
1675
|
// src/emit-include-spec.ts
|
|
1629
1676
|
function emitIncludeSpec(graph) {
|
|
1630
|
-
let out =
|
|
1677
|
+
let out = `/**
|
|
1678
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
1679
|
+
*
|
|
1680
|
+
* This file was automatically generated by PostgreSDK.
|
|
1681
|
+
* Any manual changes will be overwritten on the next generation.
|
|
1682
|
+
*
|
|
1683
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
1684
|
+
*/
|
|
1631
1685
|
`;
|
|
1632
1686
|
const tables = Object.keys(graph);
|
|
1633
1687
|
for (const table of tables) {
|
|
@@ -1656,7 +1710,14 @@ function toPascal(s) {
|
|
|
1656
1710
|
|
|
1657
1711
|
// src/emit-include-builder.ts
|
|
1658
1712
|
function emitIncludeBuilder(graph, maxDepth) {
|
|
1659
|
-
return
|
|
1713
|
+
return `/**
|
|
1714
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
1715
|
+
*
|
|
1716
|
+
* This file was automatically generated by PostgreSDK.
|
|
1717
|
+
* Any manual changes will be overwritten on the next generation.
|
|
1718
|
+
*
|
|
1719
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
1720
|
+
*/
|
|
1660
1721
|
export const RELATION_GRAPH = ${JSON.stringify(graph, null, 2)} as const;
|
|
1661
1722
|
type TableName = keyof typeof RELATION_GRAPH;
|
|
1662
1723
|
|
|
@@ -1804,7 +1865,14 @@ function emitHonoRoutes(table, _graph, opts) {
|
|
|
1804
1865
|
const hasAuth = opts.authStrategy && opts.authStrategy !== "none";
|
|
1805
1866
|
const ext = opts.useJsExtensions ? ".js" : "";
|
|
1806
1867
|
const authImport = hasAuth ? `import { authMiddleware } from "../auth${ext}";` : "";
|
|
1807
|
-
return
|
|
1868
|
+
return `/**
|
|
1869
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
1870
|
+
*
|
|
1871
|
+
* This file was automatically generated by PostgreSDK.
|
|
1872
|
+
* Any manual changes will be overwritten on the next generation.
|
|
1873
|
+
*
|
|
1874
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
1875
|
+
*/
|
|
1808
1876
|
import { Hono } from "hono";
|
|
1809
1877
|
import { z } from "zod";
|
|
1810
1878
|
import { Insert${Type}Schema, Update${Type}Schema } from "../zod/${fileTableName}${ext}";
|
|
@@ -2006,7 +2074,14 @@ function emitClient(table, graph, opts, model) {
|
|
|
2006
2074
|
`;
|
|
2007
2075
|
}
|
|
2008
2076
|
}
|
|
2009
|
-
return
|
|
2077
|
+
return `/**
|
|
2078
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2079
|
+
*
|
|
2080
|
+
* This file was automatically generated by PostgreSDK.
|
|
2081
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2082
|
+
*
|
|
2083
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2084
|
+
*/
|
|
2010
2085
|
import { BaseClient } from "./base-client${ext}";
|
|
2011
2086
|
import type { Where } from "./where-types${ext}";
|
|
2012
2087
|
${typeImports}
|
|
@@ -2053,7 +2128,14 @@ ${includeMethodsCode}}
|
|
|
2053
2128
|
}
|
|
2054
2129
|
function emitClientIndex(tables, useJsExtensions) {
|
|
2055
2130
|
const ext = useJsExtensions ? ".js" : "";
|
|
2056
|
-
let out =
|
|
2131
|
+
let out = `/**
|
|
2132
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2133
|
+
*
|
|
2134
|
+
* This file was automatically generated by PostgreSDK.
|
|
2135
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2136
|
+
*
|
|
2137
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2138
|
+
*/
|
|
2057
2139
|
`;
|
|
2058
2140
|
out += `import { BaseClient, type AuthConfig } from "./base-client${ext}";
|
|
2059
2141
|
`;
|
|
@@ -2126,7 +2208,14 @@ export type { AuthConfig, HeaderMap, AuthHeadersProvider } from "./base-client${
|
|
|
2126
2208
|
|
|
2127
2209
|
// src/emit-base-client.ts
|
|
2128
2210
|
function emitBaseClient() {
|
|
2129
|
-
return
|
|
2211
|
+
return `/**
|
|
2212
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2213
|
+
*
|
|
2214
|
+
* This file was automatically generated by PostgreSDK.
|
|
2215
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2216
|
+
*
|
|
2217
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2218
|
+
*/
|
|
2130
2219
|
|
|
2131
2220
|
export type HeaderMap = Record<string, string>;
|
|
2132
2221
|
export type AuthHeadersProvider = () => Promise<HeaderMap> | HeaderMap;
|
|
@@ -2273,7 +2362,14 @@ function emitIncludeLoader(graph, model, maxDepth, useJsExtensions) {
|
|
|
2273
2362
|
fkIndex[t.name] = t.fks.map((f) => ({ from: f.from, toTable: f.toTable, to: f.to }));
|
|
2274
2363
|
}
|
|
2275
2364
|
const ext = useJsExtensions ? ".js" : "";
|
|
2276
|
-
return
|
|
2365
|
+
return `/**
|
|
2366
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2367
|
+
*
|
|
2368
|
+
* This file was automatically generated by PostgreSDK.
|
|
2369
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2370
|
+
*
|
|
2371
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2372
|
+
*/
|
|
2277
2373
|
import { RELATION_GRAPH } from "./include-builder${ext}";
|
|
2278
2374
|
|
|
2279
2375
|
// Minimal types to keep the file self-contained
|
|
@@ -2594,7 +2690,14 @@ function emitTypes(table, opts) {
|
|
|
2594
2690
|
return ` ${col.name}: ${valueType};`;
|
|
2595
2691
|
}).join(`
|
|
2596
2692
|
`);
|
|
2597
|
-
return
|
|
2693
|
+
return `/**
|
|
2694
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2695
|
+
*
|
|
2696
|
+
* This file was automatically generated by PostgreSDK.
|
|
2697
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2698
|
+
*
|
|
2699
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2700
|
+
*/
|
|
2598
2701
|
export type Insert${Type} = {
|
|
2599
2702
|
${insertFields}
|
|
2600
2703
|
};
|
|
@@ -2609,7 +2712,14 @@ ${selectFields}
|
|
|
2609
2712
|
|
|
2610
2713
|
// src/emit-logger.ts
|
|
2611
2714
|
function emitLogger() {
|
|
2612
|
-
return
|
|
2715
|
+
return `/**
|
|
2716
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2717
|
+
*
|
|
2718
|
+
* This file was automatically generated by PostgreSDK.
|
|
2719
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2720
|
+
*
|
|
2721
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2722
|
+
*/
|
|
2613
2723
|
const DEBUG = process.env.SDK_DEBUG === "1" || process.env.SDK_DEBUG === "true";
|
|
2614
2724
|
|
|
2615
2725
|
export const logger = {
|
|
@@ -2644,7 +2754,14 @@ export function safe<T extends (c: any) => any>(handler: T) {
|
|
|
2644
2754
|
|
|
2645
2755
|
// src/emit-where-types.ts
|
|
2646
2756
|
function emitWhereTypes() {
|
|
2647
|
-
return
|
|
2757
|
+
return `/**
|
|
2758
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2759
|
+
*
|
|
2760
|
+
* This file was automatically generated by PostgreSDK.
|
|
2761
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2762
|
+
*
|
|
2763
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2764
|
+
*/
|
|
2648
2765
|
|
|
2649
2766
|
/**
|
|
2650
2767
|
* WHERE clause operators for filtering
|
|
@@ -2682,11 +2799,26 @@ export type WhereOperator<T> = {
|
|
|
2682
2799
|
export type WhereCondition<T> = T | WhereOperator<T>;
|
|
2683
2800
|
|
|
2684
2801
|
/**
|
|
2685
|
-
* WHERE
|
|
2802
|
+
* Field-level WHERE conditions (without logical operators)
|
|
2686
2803
|
*/
|
|
2687
|
-
export type
|
|
2804
|
+
export type WhereFieldConditions<T> = {
|
|
2688
2805
|
[K in keyof T]?: WhereCondition<T[K]>;
|
|
2689
2806
|
};
|
|
2807
|
+
|
|
2808
|
+
/**
|
|
2809
|
+
* WHERE clause type with support for $or/$and logical operators (2 levels max)
|
|
2810
|
+
*
|
|
2811
|
+
* Examples:
|
|
2812
|
+
* - Basic OR: { $or: [{ name: 'Alice' }, { name: 'Bob' }] }
|
|
2813
|
+
* - Mixed AND + OR: { status: 'active', $or: [{ age: { $gt: 65 } }, { age: { $lt: 18 } }] }
|
|
2814
|
+
* - Nested (2 levels): { $and: [{ $or: [{ name: 'Alice' }, { name: 'Bob' }] }, { status: 'active' }] }
|
|
2815
|
+
*/
|
|
2816
|
+
export type Where<T> = WhereFieldConditions<T> & {
|
|
2817
|
+
/** OR - at least one condition must be true */
|
|
2818
|
+
$or?: (WhereFieldConditions<T>)[];
|
|
2819
|
+
/** AND - all conditions must be true (alternative to implicit root-level AND) */
|
|
2820
|
+
$and?: (WhereFieldConditions<T> | { $or?: WhereFieldConditions<T>[] })[];
|
|
2821
|
+
};
|
|
2690
2822
|
`;
|
|
2691
2823
|
}
|
|
2692
2824
|
|
|
@@ -2704,7 +2836,14 @@ function emitAuth(cfgAuth) {
|
|
|
2704
2836
|
const JWT_SHARED_SECRET = JSON.stringify(jwtShared);
|
|
2705
2837
|
const JWT_ISSUER = jwtIssuer === undefined ? "undefined" : JSON.stringify(jwtIssuer);
|
|
2706
2838
|
const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
|
|
2707
|
-
return
|
|
2839
|
+
return `/**
|
|
2840
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
2841
|
+
*
|
|
2842
|
+
* This file was automatically generated by PostgreSDK.
|
|
2843
|
+
* Any manual changes will be overwritten on the next generation.
|
|
2844
|
+
*
|
|
2845
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
2846
|
+
*/
|
|
2708
2847
|
import type { Context, Next } from "hono";
|
|
2709
2848
|
|
|
2710
2849
|
// ---- Config inlined by generator ----
|
|
@@ -2861,7 +3000,14 @@ function emitHonoRouter(tables, hasAuth, useJsExtensions) {
|
|
|
2861
3000
|
return `export { register${Type}Routes } from "./routes/${name}${ext}";`;
|
|
2862
3001
|
}).join(`
|
|
2863
3002
|
`);
|
|
2864
|
-
return
|
|
3003
|
+
return `/**
|
|
3004
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3005
|
+
*
|
|
3006
|
+
* This file was automatically generated by PostgreSDK.
|
|
3007
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3008
|
+
*
|
|
3009
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3010
|
+
*/
|
|
2865
3011
|
import { Hono } from "hono";
|
|
2866
3012
|
import { SDK_MANIFEST } from "./sdk-bundle${ext}";
|
|
2867
3013
|
import { getContract } from "./contract${ext}";
|
|
@@ -2995,7 +3141,14 @@ function emitSdkBundle(clientFiles, clientDir) {
|
|
|
2995
3141
|
}
|
|
2996
3142
|
const version = `1.0.0`;
|
|
2997
3143
|
const generated = new Date().toISOString();
|
|
2998
|
-
return
|
|
3144
|
+
return `/**
|
|
3145
|
+
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
3146
|
+
*
|
|
3147
|
+
* This file was automatically generated by PostgreSDK.
|
|
3148
|
+
* Any manual changes will be overwritten on the next generation.
|
|
3149
|
+
*
|
|
3150
|
+
* To make changes, modify your schema or configuration and regenerate.
|
|
3151
|
+
*/
|
|
2999
3152
|
|
|
3000
3153
|
export const SDK_MANIFEST = {
|
|
3001
3154
|
version: "${version}",
|
|
@@ -3099,6 +3252,155 @@ export async function getByPk(
|
|
|
3099
3252
|
}
|
|
3100
3253
|
}
|
|
3101
3254
|
|
|
3255
|
+
/**
|
|
3256
|
+
* Build WHERE clause recursively, supporting $or/$and operators
|
|
3257
|
+
* Returns { sql: string, params: any[], nextParamIndex: number }
|
|
3258
|
+
*/
|
|
3259
|
+
function buildWhereClause(
|
|
3260
|
+
whereClause: any,
|
|
3261
|
+
startParamIndex: number
|
|
3262
|
+
): { sql: string; params: any[]; nextParamIndex: number } {
|
|
3263
|
+
const whereParts: string[] = [];
|
|
3264
|
+
const whereParams: any[] = [];
|
|
3265
|
+
let paramIndex = startParamIndex;
|
|
3266
|
+
|
|
3267
|
+
if (!whereClause || typeof whereClause !== 'object') {
|
|
3268
|
+
return { sql: '', params: [], nextParamIndex: paramIndex };
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
// Separate logical operators from field conditions
|
|
3272
|
+
const { $or, $and, ...fieldConditions } = whereClause;
|
|
3273
|
+
|
|
3274
|
+
// Process field-level conditions
|
|
3275
|
+
for (const [key, value] of Object.entries(fieldConditions)) {
|
|
3276
|
+
if (value === undefined) {
|
|
3277
|
+
continue;
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
// Handle operator objects like { $gt: 5, $like: "%test%" }
|
|
3281
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
3282
|
+
for (const [op, opValue] of Object.entries(value)) {
|
|
3283
|
+
if (opValue === undefined) continue;
|
|
3284
|
+
|
|
3285
|
+
switch (op) {
|
|
3286
|
+
case '$eq':
|
|
3287
|
+
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3288
|
+
whereParams.push(opValue);
|
|
3289
|
+
paramIndex++;
|
|
3290
|
+
break;
|
|
3291
|
+
case '$ne':
|
|
3292
|
+
whereParts.push(\`"\${key}" != $\${paramIndex}\`);
|
|
3293
|
+
whereParams.push(opValue);
|
|
3294
|
+
paramIndex++;
|
|
3295
|
+
break;
|
|
3296
|
+
case '$gt':
|
|
3297
|
+
whereParts.push(\`"\${key}" > $\${paramIndex}\`);
|
|
3298
|
+
whereParams.push(opValue);
|
|
3299
|
+
paramIndex++;
|
|
3300
|
+
break;
|
|
3301
|
+
case '$gte':
|
|
3302
|
+
whereParts.push(\`"\${key}" >= $\${paramIndex}\`);
|
|
3303
|
+
whereParams.push(opValue);
|
|
3304
|
+
paramIndex++;
|
|
3305
|
+
break;
|
|
3306
|
+
case '$lt':
|
|
3307
|
+
whereParts.push(\`"\${key}" < $\${paramIndex}\`);
|
|
3308
|
+
whereParams.push(opValue);
|
|
3309
|
+
paramIndex++;
|
|
3310
|
+
break;
|
|
3311
|
+
case '$lte':
|
|
3312
|
+
whereParts.push(\`"\${key}" <= $\${paramIndex}\`);
|
|
3313
|
+
whereParams.push(opValue);
|
|
3314
|
+
paramIndex++;
|
|
3315
|
+
break;
|
|
3316
|
+
case '$in':
|
|
3317
|
+
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3318
|
+
whereParts.push(\`"\${key}" = ANY($\${paramIndex})\`);
|
|
3319
|
+
whereParams.push(opValue);
|
|
3320
|
+
paramIndex++;
|
|
3321
|
+
}
|
|
3322
|
+
break;
|
|
3323
|
+
case '$nin':
|
|
3324
|
+
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3325
|
+
whereParts.push(\`"\${key}" != ALL($\${paramIndex})\`);
|
|
3326
|
+
whereParams.push(opValue);
|
|
3327
|
+
paramIndex++;
|
|
3328
|
+
}
|
|
3329
|
+
break;
|
|
3330
|
+
case '$like':
|
|
3331
|
+
whereParts.push(\`"\${key}" LIKE $\${paramIndex}\`);
|
|
3332
|
+
whereParams.push(opValue);
|
|
3333
|
+
paramIndex++;
|
|
3334
|
+
break;
|
|
3335
|
+
case '$ilike':
|
|
3336
|
+
whereParts.push(\`"\${key}" ILIKE $\${paramIndex}\`);
|
|
3337
|
+
whereParams.push(opValue);
|
|
3338
|
+
paramIndex++;
|
|
3339
|
+
break;
|
|
3340
|
+
case '$is':
|
|
3341
|
+
if (opValue === null) {
|
|
3342
|
+
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3343
|
+
}
|
|
3344
|
+
break;
|
|
3345
|
+
case '$isNot':
|
|
3346
|
+
if (opValue === null) {
|
|
3347
|
+
whereParts.push(\`"\${key}" IS NOT NULL\`);
|
|
3348
|
+
}
|
|
3349
|
+
break;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
} else if (value === null) {
|
|
3353
|
+
// Direct null value
|
|
3354
|
+
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3355
|
+
} else {
|
|
3356
|
+
// Direct value (simple equality)
|
|
3357
|
+
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3358
|
+
whereParams.push(value);
|
|
3359
|
+
paramIndex++;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3363
|
+
// Handle $or operator
|
|
3364
|
+
if ($or && Array.isArray($or)) {
|
|
3365
|
+
if ($or.length === 0) {
|
|
3366
|
+
// Empty OR is logically FALSE - matches nothing
|
|
3367
|
+
whereParts.push('FALSE');
|
|
3368
|
+
} else {
|
|
3369
|
+
const orParts: string[] = [];
|
|
3370
|
+
for (const orCondition of $or) {
|
|
3371
|
+
const result = buildWhereClause(orCondition, paramIndex);
|
|
3372
|
+
if (result.sql) {
|
|
3373
|
+
orParts.push(result.sql);
|
|
3374
|
+
whereParams.push(...result.params);
|
|
3375
|
+
paramIndex = result.nextParamIndex;
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
if (orParts.length > 0) {
|
|
3379
|
+
whereParts.push(\`(\${orParts.join(' OR ')})\`);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
|
|
3384
|
+
// Handle $and operator
|
|
3385
|
+
if ($and && Array.isArray($and) && $and.length > 0) {
|
|
3386
|
+
const andParts: string[] = [];
|
|
3387
|
+
for (const andCondition of $and) {
|
|
3388
|
+
const result = buildWhereClause(andCondition, paramIndex);
|
|
3389
|
+
if (result.sql) {
|
|
3390
|
+
andParts.push(result.sql);
|
|
3391
|
+
whereParams.push(...result.params);
|
|
3392
|
+
paramIndex = result.nextParamIndex;
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
if (andParts.length > 0) {
|
|
3396
|
+
whereParts.push(\`(\${andParts.join(' AND ')})\`);
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
const sql = whereParts.join(' AND ');
|
|
3401
|
+
return { sql, params: whereParams, nextParamIndex: paramIndex };
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3102
3404
|
/**
|
|
3103
3405
|
* LIST operation - Get multiple records with optional filters
|
|
3104
3406
|
*/
|
|
@@ -3108,136 +3410,54 @@ export async function listRecords(
|
|
|
3108
3410
|
): Promise<{ data?: any; error?: string; issues?: any; needsIncludes?: boolean; includeSpec?: any; status: number }> {
|
|
3109
3411
|
try {
|
|
3110
3412
|
const { where: whereClause, limit = 50, offset = 0, include } = params;
|
|
3111
|
-
|
|
3413
|
+
|
|
3112
3414
|
// Build WHERE clause
|
|
3113
|
-
const whereParts: string[] = [];
|
|
3114
|
-
const whereParams: any[] = [];
|
|
3115
3415
|
let paramIndex = 1;
|
|
3116
|
-
|
|
3416
|
+
const whereParts: string[] = [];
|
|
3417
|
+
let whereParams: any[] = [];
|
|
3418
|
+
|
|
3117
3419
|
// Add soft delete filter if applicable
|
|
3118
3420
|
if (ctx.softDeleteColumn) {
|
|
3119
3421
|
whereParts.push(\`"\${ctx.softDeleteColumn}" IS NULL\`);
|
|
3120
3422
|
}
|
|
3121
|
-
|
|
3122
|
-
// Add user-provided where conditions
|
|
3123
|
-
if (whereClause && typeof whereClause === 'object') {
|
|
3124
|
-
for (const [key, value] of Object.entries(whereClause)) {
|
|
3125
|
-
if (value === undefined) {
|
|
3126
|
-
// Skip undefined values
|
|
3127
|
-
continue;
|
|
3128
|
-
}
|
|
3129
3423
|
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3138
|
-
whereParams.push(opValue);
|
|
3139
|
-
paramIndex++;
|
|
3140
|
-
break;
|
|
3141
|
-
case '$ne':
|
|
3142
|
-
whereParts.push(\`"\${key}" != $\${paramIndex}\`);
|
|
3143
|
-
whereParams.push(opValue);
|
|
3144
|
-
paramIndex++;
|
|
3145
|
-
break;
|
|
3146
|
-
case '$gt':
|
|
3147
|
-
whereParts.push(\`"\${key}" > $\${paramIndex}\`);
|
|
3148
|
-
whereParams.push(opValue);
|
|
3149
|
-
paramIndex++;
|
|
3150
|
-
break;
|
|
3151
|
-
case '$gte':
|
|
3152
|
-
whereParts.push(\`"\${key}" >= $\${paramIndex}\`);
|
|
3153
|
-
whereParams.push(opValue);
|
|
3154
|
-
paramIndex++;
|
|
3155
|
-
break;
|
|
3156
|
-
case '$lt':
|
|
3157
|
-
whereParts.push(\`"\${key}" < $\${paramIndex}\`);
|
|
3158
|
-
whereParams.push(opValue);
|
|
3159
|
-
paramIndex++;
|
|
3160
|
-
break;
|
|
3161
|
-
case '$lte':
|
|
3162
|
-
whereParts.push(\`"\${key}" <= $\${paramIndex}\`);
|
|
3163
|
-
whereParams.push(opValue);
|
|
3164
|
-
paramIndex++;
|
|
3165
|
-
break;
|
|
3166
|
-
case '$in':
|
|
3167
|
-
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3168
|
-
whereParts.push(\`"\${key}" = ANY($\${paramIndex})\`);
|
|
3169
|
-
whereParams.push(opValue);
|
|
3170
|
-
paramIndex++;
|
|
3171
|
-
}
|
|
3172
|
-
break;
|
|
3173
|
-
case '$nin':
|
|
3174
|
-
if (Array.isArray(opValue) && opValue.length > 0) {
|
|
3175
|
-
whereParts.push(\`"\${key}" != ALL($\${paramIndex})\`);
|
|
3176
|
-
whereParams.push(opValue);
|
|
3177
|
-
paramIndex++;
|
|
3178
|
-
}
|
|
3179
|
-
break;
|
|
3180
|
-
case '$like':
|
|
3181
|
-
whereParts.push(\`"\${key}" LIKE $\${paramIndex}\`);
|
|
3182
|
-
whereParams.push(opValue);
|
|
3183
|
-
paramIndex++;
|
|
3184
|
-
break;
|
|
3185
|
-
case '$ilike':
|
|
3186
|
-
whereParts.push(\`"\${key}" ILIKE $\${paramIndex}\`);
|
|
3187
|
-
whereParams.push(opValue);
|
|
3188
|
-
paramIndex++;
|
|
3189
|
-
break;
|
|
3190
|
-
case '$is':
|
|
3191
|
-
if (opValue === null) {
|
|
3192
|
-
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3193
|
-
}
|
|
3194
|
-
break;
|
|
3195
|
-
case '$isNot':
|
|
3196
|
-
if (opValue === null) {
|
|
3197
|
-
whereParts.push(\`"\${key}" IS NOT NULL\`);
|
|
3198
|
-
}
|
|
3199
|
-
break;
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
} else if (value === null) {
|
|
3203
|
-
// Direct null value
|
|
3204
|
-
whereParts.push(\`"\${key}" IS NULL\`);
|
|
3205
|
-
} else {
|
|
3206
|
-
// Direct value (simple equality)
|
|
3207
|
-
whereParts.push(\`"\${key}" = $\${paramIndex}\`);
|
|
3208
|
-
whereParams.push(value);
|
|
3209
|
-
paramIndex++;
|
|
3210
|
-
}
|
|
3424
|
+
// Add user-provided where conditions
|
|
3425
|
+
if (whereClause) {
|
|
3426
|
+
const result = buildWhereClause(whereClause, paramIndex);
|
|
3427
|
+
if (result.sql) {
|
|
3428
|
+
whereParts.push(result.sql);
|
|
3429
|
+
whereParams = result.params;
|
|
3430
|
+
paramIndex = result.nextParamIndex;
|
|
3211
3431
|
}
|
|
3212
3432
|
}
|
|
3213
|
-
|
|
3433
|
+
|
|
3214
3434
|
const whereSQL = whereParts.length > 0 ? \`WHERE \${whereParts.join(" AND ")}\` : "";
|
|
3215
|
-
|
|
3435
|
+
|
|
3216
3436
|
// Add limit and offset params
|
|
3217
3437
|
const limitParam = \`$\${paramIndex}\`;
|
|
3218
3438
|
const offsetParam = \`$\${paramIndex + 1}\`;
|
|
3219
3439
|
const allParams = [...whereParams, limit, offset];
|
|
3220
|
-
|
|
3440
|
+
|
|
3221
3441
|
const text = \`SELECT * FROM "\${ctx.table}" \${whereSQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
3222
3442
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
3223
|
-
|
|
3443
|
+
|
|
3224
3444
|
const { rows } = await ctx.pg.query(text, allParams);
|
|
3225
|
-
|
|
3445
|
+
|
|
3226
3446
|
if (!include) {
|
|
3227
3447
|
log.debug(\`LIST \${ctx.table} rows:\`, rows.length);
|
|
3228
3448
|
return { data: rows, status: 200 };
|
|
3229
3449
|
}
|
|
3230
|
-
|
|
3450
|
+
|
|
3231
3451
|
// Include logic will be handled by the include-loader
|
|
3232
3452
|
// For now, just return the rows with a note that includes need to be applied
|
|
3233
3453
|
log.debug(\`LIST \${ctx.table} include spec:\`, include);
|
|
3234
3454
|
return { data: rows, needsIncludes: true, includeSpec: include, status: 200 };
|
|
3235
3455
|
} catch (e: any) {
|
|
3236
3456
|
log.error(\`LIST \${ctx.table} error:\`, e?.stack ?? e);
|
|
3237
|
-
return {
|
|
3238
|
-
error: e?.message ?? "Internal error",
|
|
3457
|
+
return {
|
|
3458
|
+
error: e?.message ?? "Internal error",
|
|
3239
3459
|
...(DEBUG ? { stack: e?.stack } : {}),
|
|
3240
|
-
status: 500
|
|
3460
|
+
status: 500
|
|
3241
3461
|
};
|
|
3242
3462
|
}
|
|
3243
3463
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postgresdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Generate a typed server/client SDK from a Postgres schema (includes, Zod, Hono).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "bun build src/cli.ts src/index.ts --outdir dist --target node --format esm --external=pg --external=zod --external=hono --external=prompts --external=node:* && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
25
|
-
"test": "bun test:init && bun test:gen && bun test test/test-where-clause.test.ts && bun test:gen-with-tests && bun test:pull && bun test:typecheck && bun test:drizzle-e2e",
|
|
25
|
+
"test": "bun test:init && bun test:gen && bun test test/test-where-clause.test.ts && bun test test/test-where-or-and.test.ts && bun test:gen-with-tests && bun test:pull && bun test:typecheck && bun test:drizzle-e2e",
|
|
26
26
|
"test:init": "bun test/test-init.ts",
|
|
27
27
|
"test:gen": "bun test/test-gen.ts",
|
|
28
28
|
"test:gen-with-tests": "bun test/test-gen-with-tests.ts",
|
|
@@ -53,7 +53,16 @@
|
|
|
53
53
|
"typescript": "^5.5.0",
|
|
54
54
|
"vitest": "^3.2.4"
|
|
55
55
|
},
|
|
56
|
+
"author": "Ben Honda <ben@theadpharm.com>",
|
|
56
57
|
"license": "MIT",
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/adpharm/postgresdk.git"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://github.com/adpharm/postgresdk#readme",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/adpharm/postgresdk/issues"
|
|
65
|
+
},
|
|
57
66
|
"keywords": [
|
|
58
67
|
"postgres",
|
|
59
68
|
"sdk",
|