postgresdk 0.16.5 → 0.16.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +27 -11
- package/dist/index.js +27 -11
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4682,6 +4682,22 @@ const log = {
|
|
|
4682
4682
|
error: (...args: any[]) => console.error("[sdk]", ...args),
|
|
4683
4683
|
};
|
|
4684
4684
|
|
|
4685
|
+
/**
|
|
4686
|
+
* Prepare query parameters for PostgreSQL.
|
|
4687
|
+
* The pg library should handle JSONB automatically, but there are edge cases
|
|
4688
|
+
* where explicit stringification is needed (e.g., certain pg versions or when
|
|
4689
|
+
* objects have been through serialization/deserialization).
|
|
4690
|
+
*/
|
|
4691
|
+
function prepareParams(params: any[]): any[] {
|
|
4692
|
+
return params.map(p => {
|
|
4693
|
+
if (p === null || p === undefined) return p;
|
|
4694
|
+
// Stringify objects/arrays for JSONB - while pg should handle this automatically,
|
|
4695
|
+
// we've observed cases where it fails without explicit stringification
|
|
4696
|
+
if (typeof p === 'object') return JSON.stringify(p);
|
|
4697
|
+
return p;
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
|
|
4685
4701
|
/**
|
|
4686
4702
|
* CREATE operation - Insert a new record
|
|
4687
4703
|
*/
|
|
@@ -4701,9 +4717,9 @@ export async function createRecord(
|
|
|
4701
4717
|
const text = \`INSERT INTO "\${ctx.table}" (\${cols.map(c => '"' + c + '"').join(", ")})
|
|
4702
4718
|
VALUES (\${placeholders})
|
|
4703
4719
|
RETURNING *\`;
|
|
4704
|
-
|
|
4720
|
+
|
|
4705
4721
|
log.debug("SQL:", text, "vals:", vals);
|
|
4706
|
-
const { rows } = await ctx.pg.query(text, vals);
|
|
4722
|
+
const { rows } = await ctx.pg.query(text, prepareParams(vals));
|
|
4707
4723
|
|
|
4708
4724
|
return { data: rows[0] ?? null, status: rows[0] ? 201 : 500 };
|
|
4709
4725
|
} catch (e: any) {
|
|
@@ -4742,8 +4758,8 @@ export async function getByPk(
|
|
|
4742
4758
|
|
|
4743
4759
|
const text = \`SELECT * FROM "\${ctx.table}" WHERE \${wherePkSql} LIMIT 1\`;
|
|
4744
4760
|
log.debug(\`GET \${ctx.table} by PK:\`, pkValues, "SQL:", text);
|
|
4745
|
-
|
|
4746
|
-
const { rows } = await ctx.pg.query(text, pkValues);
|
|
4761
|
+
|
|
4762
|
+
const { rows } = await ctx.pg.query(text, prepareParams(pkValues));
|
|
4747
4763
|
|
|
4748
4764
|
if (!rows[0]) {
|
|
4749
4765
|
return { data: null, status: 404 };
|
|
@@ -5127,14 +5143,14 @@ export async function listRecords(
|
|
|
5127
5143
|
// Get total count for pagination
|
|
5128
5144
|
const countText = \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
|
|
5129
5145
|
log.debug(\`LIST \${ctx.table} COUNT SQL:\`, countText, "params:", countParams);
|
|
5130
|
-
const countResult = await ctx.pg.query(countText, countParams);
|
|
5146
|
+
const countResult = await ctx.pg.query(countText, prepareParams(countParams));
|
|
5131
5147
|
const total = parseInt(countResult.rows[0].count, 10);
|
|
5132
5148
|
|
|
5133
5149
|
// Get paginated data
|
|
5134
5150
|
const text = \`SELECT \${selectClause} FROM "\${ctx.table}" \${whereSQL} \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
5135
5151
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
5136
5152
|
|
|
5137
|
-
const { rows } = await ctx.pg.query(text, allParams);
|
|
5153
|
+
const { rows } = await ctx.pg.query(text, prepareParams(allParams));
|
|
5138
5154
|
|
|
5139
5155
|
// Calculate hasMore
|
|
5140
5156
|
const hasMore = offset + limit < total;
|
|
@@ -5199,12 +5215,12 @@ export async function updateRecord(
|
|
|
5199
5215
|
const setSql = Object.keys(filteredData)
|
|
5200
5216
|
.map((k, i) => \`"\${k}" = $\${i + pkValues.length + 1}\`)
|
|
5201
5217
|
.join(", ");
|
|
5202
|
-
|
|
5218
|
+
|
|
5203
5219
|
const text = \`UPDATE "\${ctx.table}" SET \${setSql} WHERE \${wherePkSql} RETURNING *\`;
|
|
5204
5220
|
const params = [...pkValues, ...Object.values(filteredData)];
|
|
5205
|
-
|
|
5221
|
+
|
|
5206
5222
|
log.debug(\`PATCH \${ctx.table} SQL:\`, text, "params:", params);
|
|
5207
|
-
const { rows } = await ctx.pg.query(text, params);
|
|
5223
|
+
const { rows } = await ctx.pg.query(text, prepareParams(params));
|
|
5208
5224
|
|
|
5209
5225
|
if (!rows[0]) {
|
|
5210
5226
|
return { data: null, status: 404 };
|
|
@@ -5251,9 +5267,9 @@ export async function deleteRecord(
|
|
|
5251
5267
|
const text = ctx.softDeleteColumn
|
|
5252
5268
|
? \`UPDATE "\${ctx.table}" SET "\${ctx.softDeleteColumn}" = NOW() WHERE \${wherePkSql} RETURNING *\`
|
|
5253
5269
|
: \`DELETE FROM "\${ctx.table}" WHERE \${wherePkSql} RETURNING *\`;
|
|
5254
|
-
|
|
5270
|
+
|
|
5255
5271
|
log.debug(\`DELETE \${ctx.softDeleteColumn ? '(soft)' : ''} \${ctx.table} SQL:\`, text, "pk:", pkValues);
|
|
5256
|
-
const { rows } = await ctx.pg.query(text, pkValues);
|
|
5272
|
+
const { rows } = await ctx.pg.query(text, prepareParams(pkValues));
|
|
5257
5273
|
|
|
5258
5274
|
if (!rows[0]) {
|
|
5259
5275
|
return { data: null, status: 404 };
|
package/dist/index.js
CHANGED
|
@@ -3853,6 +3853,22 @@ const log = {
|
|
|
3853
3853
|
error: (...args: any[]) => console.error("[sdk]", ...args),
|
|
3854
3854
|
};
|
|
3855
3855
|
|
|
3856
|
+
/**
|
|
3857
|
+
* Prepare query parameters for PostgreSQL.
|
|
3858
|
+
* The pg library should handle JSONB automatically, but there are edge cases
|
|
3859
|
+
* where explicit stringification is needed (e.g., certain pg versions or when
|
|
3860
|
+
* objects have been through serialization/deserialization).
|
|
3861
|
+
*/
|
|
3862
|
+
function prepareParams(params: any[]): any[] {
|
|
3863
|
+
return params.map(p => {
|
|
3864
|
+
if (p === null || p === undefined) return p;
|
|
3865
|
+
// Stringify objects/arrays for JSONB - while pg should handle this automatically,
|
|
3866
|
+
// we've observed cases where it fails without explicit stringification
|
|
3867
|
+
if (typeof p === 'object') return JSON.stringify(p);
|
|
3868
|
+
return p;
|
|
3869
|
+
});
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3856
3872
|
/**
|
|
3857
3873
|
* CREATE operation - Insert a new record
|
|
3858
3874
|
*/
|
|
@@ -3872,9 +3888,9 @@ export async function createRecord(
|
|
|
3872
3888
|
const text = \`INSERT INTO "\${ctx.table}" (\${cols.map(c => '"' + c + '"').join(", ")})
|
|
3873
3889
|
VALUES (\${placeholders})
|
|
3874
3890
|
RETURNING *\`;
|
|
3875
|
-
|
|
3891
|
+
|
|
3876
3892
|
log.debug("SQL:", text, "vals:", vals);
|
|
3877
|
-
const { rows } = await ctx.pg.query(text, vals);
|
|
3893
|
+
const { rows } = await ctx.pg.query(text, prepareParams(vals));
|
|
3878
3894
|
|
|
3879
3895
|
return { data: rows[0] ?? null, status: rows[0] ? 201 : 500 };
|
|
3880
3896
|
} catch (e: any) {
|
|
@@ -3913,8 +3929,8 @@ export async function getByPk(
|
|
|
3913
3929
|
|
|
3914
3930
|
const text = \`SELECT * FROM "\${ctx.table}" WHERE \${wherePkSql} LIMIT 1\`;
|
|
3915
3931
|
log.debug(\`GET \${ctx.table} by PK:\`, pkValues, "SQL:", text);
|
|
3916
|
-
|
|
3917
|
-
const { rows } = await ctx.pg.query(text, pkValues);
|
|
3932
|
+
|
|
3933
|
+
const { rows } = await ctx.pg.query(text, prepareParams(pkValues));
|
|
3918
3934
|
|
|
3919
3935
|
if (!rows[0]) {
|
|
3920
3936
|
return { data: null, status: 404 };
|
|
@@ -4298,14 +4314,14 @@ export async function listRecords(
|
|
|
4298
4314
|
// Get total count for pagination
|
|
4299
4315
|
const countText = \`SELECT COUNT(*) FROM "\${ctx.table}" \${countWhereSQL}\`;
|
|
4300
4316
|
log.debug(\`LIST \${ctx.table} COUNT SQL:\`, countText, "params:", countParams);
|
|
4301
|
-
const countResult = await ctx.pg.query(countText, countParams);
|
|
4317
|
+
const countResult = await ctx.pg.query(countText, prepareParams(countParams));
|
|
4302
4318
|
const total = parseInt(countResult.rows[0].count, 10);
|
|
4303
4319
|
|
|
4304
4320
|
// Get paginated data
|
|
4305
4321
|
const text = \`SELECT \${selectClause} FROM "\${ctx.table}" \${whereSQL} \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
4306
4322
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
4307
4323
|
|
|
4308
|
-
const { rows } = await ctx.pg.query(text, allParams);
|
|
4324
|
+
const { rows } = await ctx.pg.query(text, prepareParams(allParams));
|
|
4309
4325
|
|
|
4310
4326
|
// Calculate hasMore
|
|
4311
4327
|
const hasMore = offset + limit < total;
|
|
@@ -4370,12 +4386,12 @@ export async function updateRecord(
|
|
|
4370
4386
|
const setSql = Object.keys(filteredData)
|
|
4371
4387
|
.map((k, i) => \`"\${k}" = $\${i + pkValues.length + 1}\`)
|
|
4372
4388
|
.join(", ");
|
|
4373
|
-
|
|
4389
|
+
|
|
4374
4390
|
const text = \`UPDATE "\${ctx.table}" SET \${setSql} WHERE \${wherePkSql} RETURNING *\`;
|
|
4375
4391
|
const params = [...pkValues, ...Object.values(filteredData)];
|
|
4376
|
-
|
|
4392
|
+
|
|
4377
4393
|
log.debug(\`PATCH \${ctx.table} SQL:\`, text, "params:", params);
|
|
4378
|
-
const { rows } = await ctx.pg.query(text, params);
|
|
4394
|
+
const { rows } = await ctx.pg.query(text, prepareParams(params));
|
|
4379
4395
|
|
|
4380
4396
|
if (!rows[0]) {
|
|
4381
4397
|
return { data: null, status: 404 };
|
|
@@ -4422,9 +4438,9 @@ export async function deleteRecord(
|
|
|
4422
4438
|
const text = ctx.softDeleteColumn
|
|
4423
4439
|
? \`UPDATE "\${ctx.table}" SET "\${ctx.softDeleteColumn}" = NOW() WHERE \${wherePkSql} RETURNING *\`
|
|
4424
4440
|
: \`DELETE FROM "\${ctx.table}" WHERE \${wherePkSql} RETURNING *\`;
|
|
4425
|
-
|
|
4441
|
+
|
|
4426
4442
|
log.debug(\`DELETE \${ctx.softDeleteColumn ? '(soft)' : ''} \${ctx.table} SQL:\`, text, "pk:", pkValues);
|
|
4427
|
-
const { rows } = await ctx.pg.query(text, pkValues);
|
|
4443
|
+
const { rows } = await ctx.pg.query(text, prepareParams(pkValues));
|
|
4428
4444
|
|
|
4429
4445
|
if (!rows[0]) {
|
|
4430
4446
|
return { data: null, status: 404 };
|