@graffy/pg 0.16.20-alpha.11 → 0.16.20-alpha.12

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/index.cjs CHANGED
@@ -88,13 +88,16 @@ const getJsonBuildTrusted = (variadic) => {
88
88
  return sql`jsonb_build_object(${args})`;
89
89
  };
90
90
  const getJsonBuildValue = (value) => {
91
- if (value instanceof Sql) return value;
92
- if (typeof value === "string") return sql`${value}::text`;
91
+ if (value instanceof Sql)
92
+ return value;
93
+ if (typeof value === "string")
94
+ return sql`${value}::text`;
93
95
  return sql`${JSON.stringify(stripAttributes(value))}::jsonb`;
94
96
  };
95
97
  const lookup = (prop, options) => {
96
98
  const [prefix, ...suffix] = prop.split(".");
97
- if (!suffix.length) return sql`"${raw(prefix)}"`;
99
+ if (!suffix.length)
100
+ return sql`"${raw(prefix)}"`;
98
101
  const { types: types2 } = options.schema;
99
102
  if (types2[prefix] === "jsonb") {
100
103
  return sql`"${raw(prefix)}" #> ${suffix}`;
@@ -117,7 +120,8 @@ const aggSql = {
117
120
  $min: (prop) => sql`min((${lookupNumeric(prop)})::numeric)`
118
121
  };
119
122
  const getSelectCols = (options, projection = null) => {
120
- if (!projection) return sql`*`;
123
+ if (!projection)
124
+ return sql`*`;
121
125
  const sqls = [];
122
126
  for (const key in projection) {
123
127
  if (key === "$count") {
@@ -151,14 +155,45 @@ function cubeLiteralSql(value) {
151
155
  )})` : sql`cube(${vertexSql(value, 0)})`;
152
156
  }
153
157
  function castValue(value, type, name, isPut) {
154
- if (!type) throw Error(`pg.write_no_column ${name}`);
155
- if (value instanceof Sql) return value;
156
- if (value === null) return sql`NULL`;
158
+ if (!type)
159
+ throw Error(`pg.write_no_column ${name}`);
160
+ if (value instanceof Sql)
161
+ return value;
162
+ if (value === null)
163
+ return sql`NULL`;
157
164
  if (type === "jsonb") {
158
- return isPut ? JSON.stringify(stripAttributes(value)) : getJsonUpdate(value, name, [])[0];
165
+ return buildJsonPartial(value, isPut);
159
166
  }
160
- if (type === "cube") return cubeLiteralSql(value);
161
- return value;
167
+ if (type === "cube")
168
+ return cubeLiteralSql(value);
169
+ if (typeof value === "object" && value.$val) {
170
+ return sql`${JSON.stringify(stripAttributes(value))}::jsonb`;
171
+ }
172
+ if (typeof value === "number")
173
+ return value;
174
+ if (typeof value === "boolean")
175
+ return value;
176
+ if (typeof value === "string")
177
+ return sql`${value}`;
178
+ if (Array.isArray(value))
179
+ return sql`${JSON.stringify(value)}::jsonb`;
180
+ return sql`${JSON.stringify(value)}::jsonb`;
181
+ }
182
+ function buildJsonPartial(value, isPut) {
183
+ if (!common.isPlainObject(value)) {
184
+ return sql`${JSON.stringify(value)}::jsonb`;
185
+ }
186
+ if (Object.keys(value).length === 0 && !isPut)
187
+ return sql`NULL`;
188
+ const parts = [];
189
+ for (const k of Object.keys(value)) {
190
+ parts.push(sql`${k}::text, ${buildJsonPartial(value[k], isPut)}`);
191
+ }
192
+ if (!parts.length && isPut)
193
+ return sql`${JSON.stringify(value)}::jsonb`;
194
+ const objSql = sql`jsonb_build_object(${join(parts, ", ")})`;
195
+ const filtered = sql`(select jsonb_object_agg(key, value) from jsonb_each(${objSql}) where value <> 'null'::jsonb)`;
196
+ return filtered;
162
197
  }
163
198
  const getInsert = (rows, options) => {
164
199
  const { verCol, schema } = options;
@@ -177,7 +212,8 @@ const getInsert = (rows, options) => {
177
212
  for (const row of rows) {
178
213
  const rowVals = Array(cols.length).fill(sql`default`);
179
214
  for (const col of cols) {
180
- if (col === verCol || !(col in row)) continue;
215
+ if (col === verCol || !(col in row))
216
+ continue;
181
217
  const ix = colIx[col];
182
218
  colUsed[ix] = true;
183
219
  rowVals[ix] = castValue(row[col], schema.types[col], col, row.$put);
@@ -210,53 +246,21 @@ const getUpdates = (row, options) => {
210
246
  ", "
211
247
  );
212
248
  };
213
- function getJsonUpdate(object, col, path) {
214
- if (!object || typeof object !== "object" || Array.isArray(object) || object.$put) {
215
- const patch2 = stripAttributes(object);
216
- return [sql`${JSON.stringify(patch2)}::jsonb`, patch2 === null];
217
- }
218
- if ("$val" in object) {
219
- const value = object.$val === true ? stripAttributes(object) : object.$val;
220
- return [sql`${JSON.stringify({ $val: value })}::jsonb`, false];
221
- }
222
- const curr = sql`"${raw(col)}"${path.length ? sql`#>${path}` : empty}`;
223
- if (common.isEmpty(object)) return [curr, false];
224
- const baseSql = sql`case jsonb_typeof(${curr})
225
- when 'object' then ${curr}
226
- else '{}'::jsonb
227
- end`;
228
- let maybeNull = true;
229
- let hasNulls = false;
230
- const patchSqls = Object.entries(object).map(([key, value]) => {
231
- const [valSql, nullable] = getJsonUpdate(value, col, path.concat(key));
232
- maybeNull && (maybeNull = nullable);
233
- hasNulls || (hasNulls = nullable);
234
- return sql`${key}::text, ${valSql}`;
235
- });
236
- let clause = sql`${baseSql} || jsonb_build_object(${join(patchSqls, ", ")})`;
237
- if (hasNulls) {
238
- clause = sql`(select jsonb_object_agg(key, value)
239
- from jsonb_each(${clause}) where value <> 'null'::jsonb)`;
240
- }
241
- if (maybeNull) {
242
- clause = sql`nullif(${clause}, '{}'::jsonb)`;
243
- }
244
- return [clause, maybeNull];
245
- }
246
249
  function stripAttributes(object) {
247
- if (typeof object !== "object" || !object) return object;
248
- if (Array.isArray(object)) {
250
+ if (typeof object !== "object" || !object)
251
+ return object;
252
+ if (Array.isArray(object))
249
253
  return object.map((item) => stripAttributes(item));
254
+ const res = {};
255
+ for (const k in object) {
256
+ if (k === "$put")
257
+ continue;
258
+ const val = stripAttributes(object[k]);
259
+ if (val === null)
260
+ continue;
261
+ res[k] = val;
250
262
  }
251
- return Object.entries(object).reduce(
252
- (out, [key, val]) => {
253
- if (key === "$put" || val === null) return out;
254
- if (out === null) out = {};
255
- out[key] = stripAttributes(val);
256
- return out;
257
- },
258
- null
259
- );
263
+ return Object.keys(res).length ? res : null;
260
264
  }
261
265
  const valid = {
262
266
  $eq: true,
@@ -291,21 +295,27 @@ function getAst(filter) {
291
295
  return simplify(construct(filter));
292
296
  }
293
297
  function isValidSubQuery(node) {
294
- if (!node || typeof node !== "object") return false;
298
+ if (!node || typeof node !== "object")
299
+ return false;
295
300
  const keys = Object.keys(node);
296
301
  for (const key of keys) {
297
- if (key[0] === "$" && !["$and", "$or", "$not"].includes(key)) return false;
298
- if (key[0] !== "$") return true;
302
+ if (key[0] === "$" && !["$and", "$or", "$not"].includes(key))
303
+ return false;
304
+ if (key[0] !== "$")
305
+ return true;
299
306
  }
300
307
  for (const key in node) {
301
- if (!isValidSubQuery(node[key])) return false;
308
+ if (!isValidSubQuery(node[key]))
309
+ return false;
302
310
  }
303
311
  return false;
304
312
  }
305
313
  function construct(node, prop, op) {
306
314
  if (!node || typeof node !== "object" || prop && op) {
307
- if (op && prop) return [op, prop, node];
308
- if (prop) return ["$eq", prop, node];
315
+ if (op && prop)
316
+ return [op, prop, node];
317
+ if (prop)
318
+ return ["$eq", prop, node];
309
319
  throw Error(`pgast.expected_prop_before:${JSON.stringify(node)}`);
310
320
  }
311
321
  if (Array.isArray(node)) {
@@ -324,9 +334,12 @@ function construct(node, prop, op) {
324
334
  return [key, construct(val, prop, op)];
325
335
  }
326
336
  if (key[0] === "$") {
327
- if (!valid[key]) throw Error(`pgast.invalid_op:${key}`);
328
- if (op) throw Error(`pgast.unexpected_op:${op} before:${key}`);
329
- if (!prop) throw Error(`pgast.expected_prop_before:${key}`);
337
+ if (!valid[key])
338
+ throw Error(`pgast.invalid_op:${key}`);
339
+ if (op)
340
+ throw Error(`pgast.unexpected_op:${op} before:${key}`);
341
+ if (!prop)
342
+ throw Error(`pgast.expected_prop_before:${key}`);
330
343
  return construct(val, prop, key);
331
344
  }
332
345
  return construct(val, key);
@@ -343,12 +356,16 @@ function simplify(node) {
343
356
  node[2] = simplify(node[2]);
344
357
  }
345
358
  if (op === "$and") {
346
- if (!node[1].length) return true;
347
- if (node[1].includes(false)) return false;
359
+ if (!node[1].length)
360
+ return true;
361
+ if (node[1].includes(false))
362
+ return false;
348
363
  node[1] = node[1].filter((item) => item !== true);
349
364
  } else if (op === "$or") {
350
- if (!node[1].length) return false;
351
- if (node[1].includes(true)) return true;
365
+ if (!node[1].length)
366
+ return false;
367
+ if (node[1].includes(true))
368
+ return true;
352
369
  node[1] = node[1].filter((item) => item !== false);
353
370
  } else if (op === "$not" && typeof node[1] === "boolean") {
354
371
  return !node[1];
@@ -409,12 +426,16 @@ const opSql = {
409
426
  $keyctd: sql`?&`
410
427
  };
411
428
  function getBinarySql(lhs, type, op, value, textLhs) {
412
- if (value === null && op === "$eq") return sql`${lhs} IS NULL`;
413
- if (value === null && op === "$neq") return sql`${lhs} IS NOT NULL`;
429
+ if (value === null && op === "$eq")
430
+ return sql`${lhs} IS NULL`;
431
+ if (value === null && op === "$neq")
432
+ return sql`${lhs} IS NOT NULL`;
414
433
  const sqlOp = opSql[op];
415
- if (!sqlOp) throw Error(`pg.getSql_unknown_operator ${op}`);
434
+ if (!sqlOp)
435
+ throw Error(`pg.getSql_unknown_operator ${op}`);
416
436
  if (op === "$in" || op === "$nin") {
417
- if (type === "jsonb" && typeof value[0] === "string") lhs = textLhs;
437
+ if (type === "jsonb" && typeof value[0] === "string")
438
+ lhs = textLhs;
418
439
  return sql`${lhs} ${sqlOp} (${join(value)})`;
419
440
  }
420
441
  if (op === "$re" || op === "$ire") {
@@ -433,11 +454,13 @@ function getBinarySql(lhs, type, op, value, textLhs) {
433
454
  return sql`${lhs} ${sqlOp} ${value}::text[]`;
434
455
  return sql`${lhs} ${sqlOp} ${JSON.stringify(value)}::jsonb`;
435
456
  }
436
- if (type === "cube") return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
457
+ if (type === "cube")
458
+ return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
437
459
  return sql`${lhs} ${sqlOp} ${value}`;
438
460
  }
439
461
  function getNodeSql(ast, options) {
440
- if (typeof ast === "boolean") return ast;
462
+ if (typeof ast === "boolean")
463
+ return ast;
441
464
  const op = ast[0];
442
465
  if (op === "$and" || op === "$or") {
443
466
  return sql`(${join(
@@ -450,7 +473,8 @@ function getNodeSql(ast, options) {
450
473
  }
451
474
  if (op === "$sub") {
452
475
  const joinName = ast[1];
453
- if (!options.joins[joinName]) throw Error(`pg.no_join ${joinName}`);
476
+ if (!options.joins[joinName])
477
+ throw Error(`pg.no_join ${joinName}`);
454
478
  const { idCol, schema } = options;
455
479
  const joinOptions = options.joins[joinName];
456
480
  const { table: joinTable, refCol } = options.joins[joinName];
@@ -460,7 +484,8 @@ function getNodeSql(ast, options) {
460
484
  }
461
485
  const [prefix, ...suffix] = ast[1].split(".");
462
486
  const { types: types2 = {} } = options.schema;
463
- if (!types2[prefix]) throw Error(`pg.no_column ${prefix}`);
487
+ if (!types2[prefix])
488
+ throw Error(`pg.no_column ${prefix}`);
464
489
  if (types2[prefix] === "jsonb") {
465
490
  const [lhs, textLhs] = suffix.length ? [
466
491
  sql`"${raw(prefix)}" #> ${suffix}`,
@@ -468,7 +493,8 @@ function getNodeSql(ast, options) {
468
493
  ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
469
494
  return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
470
495
  }
471
- if (suffix.length) throw Error(`pg.lookup_not_jsonb ${prefix}`);
496
+ if (suffix.length)
497
+ throw Error(`pg.lookup_not_jsonb ${prefix}`);
472
498
  return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
473
499
  }
474
500
  function getSql(filter, options) {
@@ -498,7 +524,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
498
524
  }
499
525
  const baseKey = sql`${JSON.stringify(rest)}::jsonb`;
500
526
  const where = [];
501
- if (!common.isEmpty(filter)) where.push(getSql(filter, options));
527
+ if (!common.isEmpty(filter))
528
+ where.push(getSql(filter, options));
502
529
  if (!hasRangeArg)
503
530
  return {
504
531
  meta: meta(baseKey),
@@ -513,7 +540,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
513
540
  );
514
541
  Object.entries({ $after, $before, $since, $until }).forEach(
515
542
  ([name, value]) => {
516
- if (value) where.push(getBoundCond(orderCols, value, name));
543
+ if (value)
544
+ where.push(getBoundCond(orderCols, value, name));
517
545
  }
518
546
  );
519
547
  const order = !$group && join(
@@ -597,7 +625,8 @@ function getSingleSql(arg, options) {
597
625
  };
598
626
  }
599
627
  const { where, meta } = getArgSql(arg, options);
600
- if (!(where == null ? void 0 : where.length)) throw Error("pg_write.no_condition");
628
+ if (!(where == null ? void 0 : where.length))
629
+ throw Error("pg_write.no_condition");
601
630
  return {
602
631
  where: sql`"${raw(idCol)}" = (
603
632
  SELECT "${raw(idCol)}"
@@ -718,7 +747,8 @@ class Db {
718
747
  avoid this query in every operation.
719
748
  */
720
749
  async ensureSchema(tableOptions, typeOids) {
721
- if (tableOptions.schema) return;
750
+ if (tableOptions.schema)
751
+ return;
722
752
  const { table, verCol, joins } = tableOptions;
723
753
  const tableInfoSchema = (await this.query(sql`
724
754
  SELECT table_schema, table_type
@@ -734,7 +764,8 @@ class Db {
734
764
  WHERE
735
765
  table_name = ${table} AND
736
766
  table_schema = ${tableSchema}`)).rows[0].column_types;
737
- if (!types2) throw Error(`pg.missing_table ${table}`);
767
+ if (!types2)
768
+ throw Error(`pg.missing_table ${table}`);
738
769
  typeOids = typeOids || (await this.query(sql`
739
770
  SELECT jsonb_object_agg(typname, oid) AS type_oids
740
771
  FROM pg_type
@@ -803,7 +834,8 @@ class Db {
803
834
  idQueries[args] = node.children;
804
835
  }
805
836
  }
806
- if (!common.isEmpty(idQueries)) promises.push(getByIds());
837
+ if (!common.isEmpty(idQueries))
838
+ promises.push(getByIds());
807
839
  await Promise.all(promises);
808
840
  log("dbRead", rootQuery, results);
809
841
  return common.finalize(results, common.wrap(query, prefix));
@@ -840,7 +872,8 @@ class Db {
840
872
  sqls.push(patch(object, arg, tableOptions));
841
873
  }
842
874
  }
843
- if (puts.length) sqls.push(...put(puts, tableOptions));
875
+ if (puts.length)
876
+ sqls.push(...put(puts, tableOptions));
844
877
  const result = [];
845
878
  await Promise.all(
846
879
  sqls.map(
package/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { isEmpty, isPlainObject, encodePath, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, cmp, decodeGraph, mergeObject, wrapObject, merge, encodeGraph, remove } from "@graffy/common";
1
+ import { isPlainObject, isEmpty, encodePath, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, cmp, decodeGraph, mergeObject, wrapObject, merge, encodeGraph, remove } from "@graffy/common";
2
2
  import debug from "debug";
3
3
  import pg$1 from "pg";
4
4
  class Sql {
@@ -86,13 +86,16 @@ const getJsonBuildTrusted = (variadic) => {
86
86
  return sql`jsonb_build_object(${args})`;
87
87
  };
88
88
  const getJsonBuildValue = (value) => {
89
- if (value instanceof Sql) return value;
90
- if (typeof value === "string") return sql`${value}::text`;
89
+ if (value instanceof Sql)
90
+ return value;
91
+ if (typeof value === "string")
92
+ return sql`${value}::text`;
91
93
  return sql`${JSON.stringify(stripAttributes(value))}::jsonb`;
92
94
  };
93
95
  const lookup = (prop, options) => {
94
96
  const [prefix, ...suffix] = prop.split(".");
95
- if (!suffix.length) return sql`"${raw(prefix)}"`;
97
+ if (!suffix.length)
98
+ return sql`"${raw(prefix)}"`;
96
99
  const { types: types2 } = options.schema;
97
100
  if (types2[prefix] === "jsonb") {
98
101
  return sql`"${raw(prefix)}" #> ${suffix}`;
@@ -115,7 +118,8 @@ const aggSql = {
115
118
  $min: (prop) => sql`min((${lookupNumeric(prop)})::numeric)`
116
119
  };
117
120
  const getSelectCols = (options, projection = null) => {
118
- if (!projection) return sql`*`;
121
+ if (!projection)
122
+ return sql`*`;
119
123
  const sqls = [];
120
124
  for (const key in projection) {
121
125
  if (key === "$count") {
@@ -149,14 +153,45 @@ function cubeLiteralSql(value) {
149
153
  )})` : sql`cube(${vertexSql(value, 0)})`;
150
154
  }
151
155
  function castValue(value, type, name, isPut) {
152
- if (!type) throw Error(`pg.write_no_column ${name}`);
153
- if (value instanceof Sql) return value;
154
- if (value === null) return sql`NULL`;
156
+ if (!type)
157
+ throw Error(`pg.write_no_column ${name}`);
158
+ if (value instanceof Sql)
159
+ return value;
160
+ if (value === null)
161
+ return sql`NULL`;
155
162
  if (type === "jsonb") {
156
- return isPut ? JSON.stringify(stripAttributes(value)) : getJsonUpdate(value, name, [])[0];
163
+ return buildJsonPartial(value, isPut);
157
164
  }
158
- if (type === "cube") return cubeLiteralSql(value);
159
- return value;
165
+ if (type === "cube")
166
+ return cubeLiteralSql(value);
167
+ if (typeof value === "object" && value.$val) {
168
+ return sql`${JSON.stringify(stripAttributes(value))}::jsonb`;
169
+ }
170
+ if (typeof value === "number")
171
+ return value;
172
+ if (typeof value === "boolean")
173
+ return value;
174
+ if (typeof value === "string")
175
+ return sql`${value}`;
176
+ if (Array.isArray(value))
177
+ return sql`${JSON.stringify(value)}::jsonb`;
178
+ return sql`${JSON.stringify(value)}::jsonb`;
179
+ }
180
+ function buildJsonPartial(value, isPut) {
181
+ if (!isPlainObject(value)) {
182
+ return sql`${JSON.stringify(value)}::jsonb`;
183
+ }
184
+ if (Object.keys(value).length === 0 && !isPut)
185
+ return sql`NULL`;
186
+ const parts = [];
187
+ for (const k of Object.keys(value)) {
188
+ parts.push(sql`${k}::text, ${buildJsonPartial(value[k], isPut)}`);
189
+ }
190
+ if (!parts.length && isPut)
191
+ return sql`${JSON.stringify(value)}::jsonb`;
192
+ const objSql = sql`jsonb_build_object(${join(parts, ", ")})`;
193
+ const filtered = sql`(select jsonb_object_agg(key, value) from jsonb_each(${objSql}) where value <> 'null'::jsonb)`;
194
+ return filtered;
160
195
  }
161
196
  const getInsert = (rows, options) => {
162
197
  const { verCol, schema } = options;
@@ -175,7 +210,8 @@ const getInsert = (rows, options) => {
175
210
  for (const row of rows) {
176
211
  const rowVals = Array(cols.length).fill(sql`default`);
177
212
  for (const col of cols) {
178
- if (col === verCol || !(col in row)) continue;
213
+ if (col === verCol || !(col in row))
214
+ continue;
179
215
  const ix = colIx[col];
180
216
  colUsed[ix] = true;
181
217
  rowVals[ix] = castValue(row[col], schema.types[col], col, row.$put);
@@ -208,53 +244,21 @@ const getUpdates = (row, options) => {
208
244
  ", "
209
245
  );
210
246
  };
211
- function getJsonUpdate(object, col, path) {
212
- if (!object || typeof object !== "object" || Array.isArray(object) || object.$put) {
213
- const patch2 = stripAttributes(object);
214
- return [sql`${JSON.stringify(patch2)}::jsonb`, patch2 === null];
215
- }
216
- if ("$val" in object) {
217
- const value = object.$val === true ? stripAttributes(object) : object.$val;
218
- return [sql`${JSON.stringify({ $val: value })}::jsonb`, false];
219
- }
220
- const curr = sql`"${raw(col)}"${path.length ? sql`#>${path}` : empty}`;
221
- if (isEmpty(object)) return [curr, false];
222
- const baseSql = sql`case jsonb_typeof(${curr})
223
- when 'object' then ${curr}
224
- else '{}'::jsonb
225
- end`;
226
- let maybeNull = true;
227
- let hasNulls = false;
228
- const patchSqls = Object.entries(object).map(([key, value]) => {
229
- const [valSql, nullable] = getJsonUpdate(value, col, path.concat(key));
230
- maybeNull && (maybeNull = nullable);
231
- hasNulls || (hasNulls = nullable);
232
- return sql`${key}::text, ${valSql}`;
233
- });
234
- let clause = sql`${baseSql} || jsonb_build_object(${join(patchSqls, ", ")})`;
235
- if (hasNulls) {
236
- clause = sql`(select jsonb_object_agg(key, value)
237
- from jsonb_each(${clause}) where value <> 'null'::jsonb)`;
238
- }
239
- if (maybeNull) {
240
- clause = sql`nullif(${clause}, '{}'::jsonb)`;
241
- }
242
- return [clause, maybeNull];
243
- }
244
247
  function stripAttributes(object) {
245
- if (typeof object !== "object" || !object) return object;
246
- if (Array.isArray(object)) {
248
+ if (typeof object !== "object" || !object)
249
+ return object;
250
+ if (Array.isArray(object))
247
251
  return object.map((item) => stripAttributes(item));
252
+ const res = {};
253
+ for (const k in object) {
254
+ if (k === "$put")
255
+ continue;
256
+ const val = stripAttributes(object[k]);
257
+ if (val === null)
258
+ continue;
259
+ res[k] = val;
248
260
  }
249
- return Object.entries(object).reduce(
250
- (out, [key, val]) => {
251
- if (key === "$put" || val === null) return out;
252
- if (out === null) out = {};
253
- out[key] = stripAttributes(val);
254
- return out;
255
- },
256
- null
257
- );
261
+ return Object.keys(res).length ? res : null;
258
262
  }
259
263
  const valid = {
260
264
  $eq: true,
@@ -289,21 +293,27 @@ function getAst(filter) {
289
293
  return simplify(construct(filter));
290
294
  }
291
295
  function isValidSubQuery(node) {
292
- if (!node || typeof node !== "object") return false;
296
+ if (!node || typeof node !== "object")
297
+ return false;
293
298
  const keys = Object.keys(node);
294
299
  for (const key of keys) {
295
- if (key[0] === "$" && !["$and", "$or", "$not"].includes(key)) return false;
296
- if (key[0] !== "$") return true;
300
+ if (key[0] === "$" && !["$and", "$or", "$not"].includes(key))
301
+ return false;
302
+ if (key[0] !== "$")
303
+ return true;
297
304
  }
298
305
  for (const key in node) {
299
- if (!isValidSubQuery(node[key])) return false;
306
+ if (!isValidSubQuery(node[key]))
307
+ return false;
300
308
  }
301
309
  return false;
302
310
  }
303
311
  function construct(node, prop, op) {
304
312
  if (!node || typeof node !== "object" || prop && op) {
305
- if (op && prop) return [op, prop, node];
306
- if (prop) return ["$eq", prop, node];
313
+ if (op && prop)
314
+ return [op, prop, node];
315
+ if (prop)
316
+ return ["$eq", prop, node];
307
317
  throw Error(`pgast.expected_prop_before:${JSON.stringify(node)}`);
308
318
  }
309
319
  if (Array.isArray(node)) {
@@ -322,9 +332,12 @@ function construct(node, prop, op) {
322
332
  return [key, construct(val, prop, op)];
323
333
  }
324
334
  if (key[0] === "$") {
325
- if (!valid[key]) throw Error(`pgast.invalid_op:${key}`);
326
- if (op) throw Error(`pgast.unexpected_op:${op} before:${key}`);
327
- if (!prop) throw Error(`pgast.expected_prop_before:${key}`);
335
+ if (!valid[key])
336
+ throw Error(`pgast.invalid_op:${key}`);
337
+ if (op)
338
+ throw Error(`pgast.unexpected_op:${op} before:${key}`);
339
+ if (!prop)
340
+ throw Error(`pgast.expected_prop_before:${key}`);
328
341
  return construct(val, prop, key);
329
342
  }
330
343
  return construct(val, key);
@@ -341,12 +354,16 @@ function simplify(node) {
341
354
  node[2] = simplify(node[2]);
342
355
  }
343
356
  if (op === "$and") {
344
- if (!node[1].length) return true;
345
- if (node[1].includes(false)) return false;
357
+ if (!node[1].length)
358
+ return true;
359
+ if (node[1].includes(false))
360
+ return false;
346
361
  node[1] = node[1].filter((item) => item !== true);
347
362
  } else if (op === "$or") {
348
- if (!node[1].length) return false;
349
- if (node[1].includes(true)) return true;
363
+ if (!node[1].length)
364
+ return false;
365
+ if (node[1].includes(true))
366
+ return true;
350
367
  node[1] = node[1].filter((item) => item !== false);
351
368
  } else if (op === "$not" && typeof node[1] === "boolean") {
352
369
  return !node[1];
@@ -407,12 +424,16 @@ const opSql = {
407
424
  $keyctd: sql`?&`
408
425
  };
409
426
  function getBinarySql(lhs, type, op, value, textLhs) {
410
- if (value === null && op === "$eq") return sql`${lhs} IS NULL`;
411
- if (value === null && op === "$neq") return sql`${lhs} IS NOT NULL`;
427
+ if (value === null && op === "$eq")
428
+ return sql`${lhs} IS NULL`;
429
+ if (value === null && op === "$neq")
430
+ return sql`${lhs} IS NOT NULL`;
412
431
  const sqlOp = opSql[op];
413
- if (!sqlOp) throw Error(`pg.getSql_unknown_operator ${op}`);
432
+ if (!sqlOp)
433
+ throw Error(`pg.getSql_unknown_operator ${op}`);
414
434
  if (op === "$in" || op === "$nin") {
415
- if (type === "jsonb" && typeof value[0] === "string") lhs = textLhs;
435
+ if (type === "jsonb" && typeof value[0] === "string")
436
+ lhs = textLhs;
416
437
  return sql`${lhs} ${sqlOp} (${join(value)})`;
417
438
  }
418
439
  if (op === "$re" || op === "$ire") {
@@ -431,11 +452,13 @@ function getBinarySql(lhs, type, op, value, textLhs) {
431
452
  return sql`${lhs} ${sqlOp} ${value}::text[]`;
432
453
  return sql`${lhs} ${sqlOp} ${JSON.stringify(value)}::jsonb`;
433
454
  }
434
- if (type === "cube") return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
455
+ if (type === "cube")
456
+ return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
435
457
  return sql`${lhs} ${sqlOp} ${value}`;
436
458
  }
437
459
  function getNodeSql(ast, options) {
438
- if (typeof ast === "boolean") return ast;
460
+ if (typeof ast === "boolean")
461
+ return ast;
439
462
  const op = ast[0];
440
463
  if (op === "$and" || op === "$or") {
441
464
  return sql`(${join(
@@ -448,7 +471,8 @@ function getNodeSql(ast, options) {
448
471
  }
449
472
  if (op === "$sub") {
450
473
  const joinName = ast[1];
451
- if (!options.joins[joinName]) throw Error(`pg.no_join ${joinName}`);
474
+ if (!options.joins[joinName])
475
+ throw Error(`pg.no_join ${joinName}`);
452
476
  const { idCol, schema } = options;
453
477
  const joinOptions = options.joins[joinName];
454
478
  const { table: joinTable, refCol } = options.joins[joinName];
@@ -458,7 +482,8 @@ function getNodeSql(ast, options) {
458
482
  }
459
483
  const [prefix, ...suffix] = ast[1].split(".");
460
484
  const { types: types2 = {} } = options.schema;
461
- if (!types2[prefix]) throw Error(`pg.no_column ${prefix}`);
485
+ if (!types2[prefix])
486
+ throw Error(`pg.no_column ${prefix}`);
462
487
  if (types2[prefix] === "jsonb") {
463
488
  const [lhs, textLhs] = suffix.length ? [
464
489
  sql`"${raw(prefix)}" #> ${suffix}`,
@@ -466,7 +491,8 @@ function getNodeSql(ast, options) {
466
491
  ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
467
492
  return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
468
493
  }
469
- if (suffix.length) throw Error(`pg.lookup_not_jsonb ${prefix}`);
494
+ if (suffix.length)
495
+ throw Error(`pg.lookup_not_jsonb ${prefix}`);
470
496
  return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
471
497
  }
472
498
  function getSql(filter, options) {
@@ -496,7 +522,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
496
522
  }
497
523
  const baseKey = sql`${JSON.stringify(rest)}::jsonb`;
498
524
  const where = [];
499
- if (!isEmpty(filter)) where.push(getSql(filter, options));
525
+ if (!isEmpty(filter))
526
+ where.push(getSql(filter, options));
500
527
  if (!hasRangeArg)
501
528
  return {
502
529
  meta: meta(baseKey),
@@ -511,7 +538,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
511
538
  );
512
539
  Object.entries({ $after, $before, $since, $until }).forEach(
513
540
  ([name, value]) => {
514
- if (value) where.push(getBoundCond(orderCols, value, name));
541
+ if (value)
542
+ where.push(getBoundCond(orderCols, value, name));
515
543
  }
516
544
  );
517
545
  const order = !$group && join(
@@ -595,7 +623,8 @@ function getSingleSql(arg, options) {
595
623
  };
596
624
  }
597
625
  const { where, meta } = getArgSql(arg, options);
598
- if (!(where == null ? void 0 : where.length)) throw Error("pg_write.no_condition");
626
+ if (!(where == null ? void 0 : where.length))
627
+ throw Error("pg_write.no_condition");
599
628
  return {
600
629
  where: sql`"${raw(idCol)}" = (
601
630
  SELECT "${raw(idCol)}"
@@ -716,7 +745,8 @@ class Db {
716
745
  avoid this query in every operation.
717
746
  */
718
747
  async ensureSchema(tableOptions, typeOids) {
719
- if (tableOptions.schema) return;
748
+ if (tableOptions.schema)
749
+ return;
720
750
  const { table, verCol, joins } = tableOptions;
721
751
  const tableInfoSchema = (await this.query(sql`
722
752
  SELECT table_schema, table_type
@@ -732,7 +762,8 @@ class Db {
732
762
  WHERE
733
763
  table_name = ${table} AND
734
764
  table_schema = ${tableSchema}`)).rows[0].column_types;
735
- if (!types2) throw Error(`pg.missing_table ${table}`);
765
+ if (!types2)
766
+ throw Error(`pg.missing_table ${table}`);
736
767
  typeOids = typeOids || (await this.query(sql`
737
768
  SELECT jsonb_object_agg(typname, oid) AS type_oids
738
769
  FROM pg_type
@@ -801,7 +832,8 @@ class Db {
801
832
  idQueries[args] = node.children;
802
833
  }
803
834
  }
804
- if (!isEmpty(idQueries)) promises.push(getByIds());
835
+ if (!isEmpty(idQueries))
836
+ promises.push(getByIds());
805
837
  await Promise.all(promises);
806
838
  log("dbRead", rootQuery, results);
807
839
  return finalize(results, wrap(query, prefix));
@@ -838,7 +870,8 @@ class Db {
838
870
  sqls.push(patch(object, arg, tableOptions));
839
871
  }
840
872
  }
841
- if (puts.length) sqls.push(...put(puts, tableOptions));
873
+ if (puts.length)
874
+ sqls.push(...put(puts, tableOptions));
842
875
  const result = [];
843
876
  await Promise.all(
844
877
  sqls.map(
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graffy/pg",
3
3
  "description": "The standard Postgres module for Graffy. Each instance this module mounts a Postgres table as a Graffy subtree.",
4
4
  "author": "aravind (https://github.com/aravindet)",
5
- "version": "0.16.20-alpha.11",
5
+ "version": "0.16.20-alpha.12",
6
6
  "main": "./index.cjs",
7
7
  "exports": {
8
8
  "import": "./index.mjs",
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "dependencies": {
19
- "@graffy/common": "0.16.20-alpha.11",
20
- "debug": "^4.3.7"
19
+ "@graffy/common": "0.16.20-alpha.12",
20
+ "debug": "^4.3.3"
21
21
  },
22
22
  "peerDependencies": {
23
23
  "pg": "^8.0.0"
@@ -22,4 +22,4 @@ export default function getArgSql({ $first, $last, $after, $before, $since, $unt
22
22
  /**
23
23
  * Uses the args object (typically passed in the $key attribute)
24
24
  */
25
- export type Sql = import("sql-template-tag").Sql;
25
+ export type Sql = import('sql-template-tag').Sql;