@graffy/pg 0.16.3 → 0.16.4-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -20,6 +20,9 @@ store.use(path, pg(options));
20
20
  - `table`, the name of the table. If not provided, the last segment of the `path` is used. This table must exist.
21
21
  - `idCol`: the name of the column to use as ID. Defaults to `id`. This column must exist and be the primary key or have a unique constraint.
22
22
  - `verCol`: the name of the column to store the Graffy version number. This column must exist, and must have a `DEFAULT` SQL expression defined - this expression is evaluated to calculate the version number. Graffy versions must monotonically increase, so this expression is typically based on `CURRENT_TIMESTAMP`.
23
+ - `joins`: other tables that have foreign keys referencing the ID column in this table, where we want to filter this table using columns of that other table via a "join". The value is a map of join names to join options.
24
+ - join names are the names used to refer to joined tables in filter expressions. Typically, these are the names of those tables.
25
+ - join options are objects with optional properties `table`, `idCol`, `refCol` and `verCol`. `refCol` is the name of the column in the join table that references this one.
23
26
  - `connection`: a [pg](https://github.com/brianc/node-postgres) Client or Pool object (recommended), or the arguments for constructing a new Pool object. Optional.
24
27
 
25
28
  ### Database connection
@@ -89,6 +92,9 @@ Tags must contain both *foo* and *bar*. Note that the array of conditions here d
89
92
  2. `{ tags: { $ctd: ['foo', 'bar', 'baz'] } }` becomes `tags <@ '{"foo","bar","baz"}'`.
90
93
  Every tag must be one of *foo*, *bar* or *baz*.
91
94
 
95
+ #### Joins
96
+ 1. `joinName: { ...expression }`,
97
+
92
98
  #### Notes
93
99
 
94
100
  1. We drop several MongoDB operators while retaining the capability:
package/index.cjs CHANGED
@@ -126,9 +126,7 @@ function construct(node, prop, op) {
126
126
  return construct(val, prop, key);
127
127
  }
128
128
  if (prop) {
129
- if (key[0] === ".")
130
- return construct(val, prop + key);
131
- throw Error(`pgast.unexpected_prop: ${key}`);
129
+ return ["$sub", prop, construct({ [key]: val })];
132
130
  }
133
131
  return construct(val, key);
134
132
  })
@@ -140,6 +138,8 @@ function simplify(node) {
140
138
  node[1] = node[1].map((subnode) => simplify(subnode));
141
139
  } else if (op === "$not") {
142
140
  node[1] = simplify(node[1]);
141
+ } else if (op === "$sub") {
142
+ node[2] = simplify(node[2]);
143
143
  }
144
144
  if (op === "$and") {
145
145
  if (!node[1].length)
@@ -385,36 +385,48 @@ function getBinarySql(lhs, type, op, value, textLhs) {
385
385
  return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
386
386
  return sql`${lhs} ${sqlOp} ${value}`;
387
387
  }
388
- function getSql(filter, options) {
389
- function getNodeSql(ast) {
390
- if (typeof ast === "boolean")
391
- return ast;
392
- const op = ast[0];
393
- if (op === "$and" || op === "$or") {
394
- return sql`(${join(
395
- ast[1].map((node) => getNodeSql(node)),
396
- `) ${opSql[op]} (`
397
- )})`;
398
- } else if (op === "$not") {
399
- return sql`${opSql[op]} (${getNodeSql(ast[1])})`;
400
- }
401
- const [prefix, ...suffix] = ast[1].split(".");
402
- const { types: types2 } = options.schema;
403
- if (!types2[prefix])
404
- throw Error(`pg.no_column ${prefix}`);
405
- if (types2[prefix] === "jsonb") {
406
- const [lhs, textLhs] = suffix.length ? [
407
- sql`"${raw(prefix)}" #> ${suffix}`,
408
- sql`"${raw(prefix)}" #>> ${suffix}`
409
- ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
410
- return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
411
- } else {
412
- if (suffix.length)
413
- throw Error(`pg.lookup_not_jsonb ${prefix}`);
414
- return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
415
- }
388
+ function getNodeSql(ast, options) {
389
+ if (typeof ast === "boolean")
390
+ return ast;
391
+ const op = ast[0];
392
+ if (op === "$and" || op === "$or") {
393
+ return sql`(${join(
394
+ ast[1].map((node) => getNodeSql(node, options)),
395
+ `) ${opSql[op]} (`
396
+ )})`;
397
+ } else if (op === "$not") {
398
+ return sql`${opSql[op]} (${getNodeSql(ast[1], options)})`;
399
+ }
400
+ if (op === "$sub") {
401
+ const joinName = ast[1];
402
+ if (!options.joins[joinName])
403
+ throw Error(`pg.no_join ${joinName}`);
404
+ const { idCol, schema } = options;
405
+ const joinOptions = options.joins[joinName];
406
+ const { table: joinTable, refCol } = options.joins[joinName];
407
+ return sql`"${raw(idCol)}" IN (SELECT "${raw(refCol)}"::${raw(
408
+ schema.types[idCol]
409
+ )} FROM "${raw(joinTable)}" WHERE ${getNodeSql(ast[2], joinOptions)})`;
410
+ }
411
+ const [prefix, ...suffix] = ast[1].split(".");
412
+ const { types: types2 = {} } = options.schema;
413
+ if (!types2[prefix])
414
+ throw Error(`pg.no_column ${prefix}`);
415
+ if (types2[prefix] === "jsonb") {
416
+ const [lhs, textLhs] = suffix.length ? [
417
+ sql`"${raw(prefix)}" #> ${suffix}`,
418
+ sql`"${raw(prefix)}" #>> ${suffix}`
419
+ ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
420
+ return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
421
+ } else {
422
+ if (suffix.length)
423
+ throw Error(`pg.lookup_not_jsonb ${prefix}`);
424
+ return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
416
425
  }
417
- return getNodeSql(getAst(filter));
426
+ }
427
+ function getSql(filter, options) {
428
+ const ast = getAst(filter);
429
+ return getNodeSql(ast, options);
418
430
  }
419
431
  const getIdMeta = ({ idCol, verDefault }) => sql`"${raw(idCol)}" AS "$key", ${raw(verDefault)} AS "$ver"`;
420
432
  const getArgMeta = (key, { prefix, idCol, verDefault }) => sql`
@@ -442,7 +454,12 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
442
454
  if (!common.isEmpty(filter))
443
455
  where.push(getSql(filter, options));
444
456
  if (!hasRangeArg)
445
- return { meta: meta(baseKey), where, limit: 1 };
457
+ return {
458
+ meta: meta(baseKey),
459
+ where,
460
+ limit: 1,
461
+ ensureSingleRow: $group === true
462
+ };
446
463
  const groupCols = Array.isArray($group) && $group.length && $group.map((prop) => lookup(prop, options));
447
464
  const group = groupCols ? join(groupCols, ", ") : void 0;
448
465
  const orderCols = ($order || [idCol]).map(
@@ -469,7 +486,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
469
486
  where,
470
487
  order,
471
488
  group,
472
- limit: $first || $last
489
+ limit: $first || $last,
490
+ ensureSingleRow: true
473
491
  };
474
492
  }
475
493
  function getBoundCond(orderCols, bound, kind) {
@@ -503,9 +521,23 @@ function getBoundCond(orderCols, bound, kind) {
503
521
  }
504
522
  const MAX_LIMIT = 4096;
505
523
  function selectByArgs(args, projection, options) {
506
- const { table } = options;
507
- const { where, order, group, limit, meta } = getArgSql(args, options);
524
+ const { table, idCol } = options;
525
+ const { where, order, group, limit, meta, ensureSingleRow } = getArgSql(
526
+ args,
527
+ options
528
+ );
508
529
  const clampedLimit = Math.min(MAX_LIMIT, limit || MAX_LIMIT);
530
+ if (!ensureSingleRow) {
531
+ return sql`
532
+ SELECT
533
+ ${getSelectCols(options, projection)}, ${meta}
534
+ FROM "${raw(table)}" WHERE "${raw(idCol)}" = (
535
+ SELECT "${raw(idCol)}" FROM "${raw(table)}"
536
+ ${where.length ? sql`WHERE ${join(where, " AND ")}` : empty}
537
+ LIMIT 2
538
+ )
539
+ `;
540
+ }
509
541
  return sql`
510
542
  SELECT
511
543
  ${getSelectCols(options, projection)}, ${meta}
@@ -541,7 +573,7 @@ function getSingleSql(arg, options) {
541
573
  SELECT "${raw(idCol)}"
542
574
  FROM "${raw(table)}"
543
575
  WHERE ${join(where, " AND ")}
544
- LIMIT 1
576
+ LIMIT 2
545
577
  )`,
546
578
  meta
547
579
  };
@@ -638,10 +670,10 @@ class Db {
638
670
  }
639
671
  return res.rows[0];
640
672
  }
641
- async ensureSchema(tableOptions) {
673
+ async ensureSchema(tableOptions, typeOids) {
642
674
  if (tableOptions.schema)
643
675
  return;
644
- const { table, verCol } = tableOptions;
676
+ const { table, verCol, joins } = tableOptions;
645
677
  const tableSchema = (await this.query(sql`
646
678
  SELECT table_schema
647
679
  FROM information_schema.tables
@@ -656,7 +688,7 @@ class Db {
656
688
  table_schema = ${tableSchema}`)).rows[0].column_types;
657
689
  if (!types2)
658
690
  throw Error(`pg.missing_table ${table}`);
659
- const typeOids = (await this.query(sql`
691
+ typeOids = typeOids || (await this.query(sql`
660
692
  SELECT jsonb_object_agg(typname, oid) AS type_oids
661
693
  FROM pg_type
662
694
  WHERE typname = 'cube'`)).rows[0].type_oids;
@@ -670,6 +702,11 @@ class Db {
670
702
  if (!verDefault) {
671
703
  throw Error(`pg.verCol_without_default ${verCol}`);
672
704
  }
705
+ await Promise.all(
706
+ Object.values(joins).map(
707
+ (joinOptions) => this.ensureSchema(joinOptions, typeOids)
708
+ )
709
+ );
673
710
  log("ensureSchema", types2);
674
711
  tableOptions.schema = { types: types2, typeOids };
675
712
  tableOptions.verDefault = verDefault;
@@ -760,18 +797,33 @@ class Db {
760
797
  return result;
761
798
  }
762
799
  }
763
- const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store) => {
764
- store.on("read", read);
765
- store.on("write", write);
766
- const prefix = store.path;
767
- const tableOpts = {
768
- prefix,
769
- table: table || prefix[prefix.length - 1] || "default",
800
+ function getTableOpts(name, { table, idCol, verCol, joins, schema, verDefault } = {}, parentName = null) {
801
+ const tableName = table || name;
802
+ return {
803
+ table: table || name,
770
804
  idCol: idCol || "id",
771
805
  verCol: verCol || "updatedAt",
806
+ joins: Object.fromEntries(
807
+ Object.entries(joins || {}).map(
808
+ ([joinName, { refCol = parentName, ...joinOptions }]) => [
809
+ joinName,
810
+ {
811
+ refCol,
812
+ ...getTableOpts(joinName, joinOptions, tableName)
813
+ }
814
+ ]
815
+ )
816
+ ),
772
817
  schema,
773
818
  verDefault
774
819
  };
820
+ }
821
+ const pg = ({ connection, ...rawOptions }) => (store) => {
822
+ store.on("read", read);
823
+ store.on("write", write);
824
+ const prefix = store.path;
825
+ const tableOpts = getTableOpts(prefix[prefix.length - 1], rawOptions);
826
+ tableOpts.prefix = prefix;
775
827
  const defaultDb = new Db(connection);
776
828
  function read(query, options, next) {
777
829
  const { pgClient } = options;
package/index.mjs CHANGED
@@ -124,9 +124,7 @@ function construct(node, prop, op) {
124
124
  return construct(val, prop, key);
125
125
  }
126
126
  if (prop) {
127
- if (key[0] === ".")
128
- return construct(val, prop + key);
129
- throw Error(`pgast.unexpected_prop: ${key}`);
127
+ return ["$sub", prop, construct({ [key]: val })];
130
128
  }
131
129
  return construct(val, key);
132
130
  })
@@ -138,6 +136,8 @@ function simplify(node) {
138
136
  node[1] = node[1].map((subnode) => simplify(subnode));
139
137
  } else if (op === "$not") {
140
138
  node[1] = simplify(node[1]);
139
+ } else if (op === "$sub") {
140
+ node[2] = simplify(node[2]);
141
141
  }
142
142
  if (op === "$and") {
143
143
  if (!node[1].length)
@@ -383,36 +383,48 @@ function getBinarySql(lhs, type, op, value, textLhs) {
383
383
  return sql`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
384
384
  return sql`${lhs} ${sqlOp} ${value}`;
385
385
  }
386
- function getSql(filter, options) {
387
- function getNodeSql(ast) {
388
- if (typeof ast === "boolean")
389
- return ast;
390
- const op = ast[0];
391
- if (op === "$and" || op === "$or") {
392
- return sql`(${join(
393
- ast[1].map((node) => getNodeSql(node)),
394
- `) ${opSql[op]} (`
395
- )})`;
396
- } else if (op === "$not") {
397
- return sql`${opSql[op]} (${getNodeSql(ast[1])})`;
398
- }
399
- const [prefix, ...suffix] = ast[1].split(".");
400
- const { types: types2 } = options.schema;
401
- if (!types2[prefix])
402
- throw Error(`pg.no_column ${prefix}`);
403
- if (types2[prefix] === "jsonb") {
404
- const [lhs, textLhs] = suffix.length ? [
405
- sql`"${raw(prefix)}" #> ${suffix}`,
406
- sql`"${raw(prefix)}" #>> ${suffix}`
407
- ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
408
- return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
409
- } else {
410
- if (suffix.length)
411
- throw Error(`pg.lookup_not_jsonb ${prefix}`);
412
- return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
413
- }
386
+ function getNodeSql(ast, options) {
387
+ if (typeof ast === "boolean")
388
+ return ast;
389
+ const op = ast[0];
390
+ if (op === "$and" || op === "$or") {
391
+ return sql`(${join(
392
+ ast[1].map((node) => getNodeSql(node, options)),
393
+ `) ${opSql[op]} (`
394
+ )})`;
395
+ } else if (op === "$not") {
396
+ return sql`${opSql[op]} (${getNodeSql(ast[1], options)})`;
397
+ }
398
+ if (op === "$sub") {
399
+ const joinName = ast[1];
400
+ if (!options.joins[joinName])
401
+ throw Error(`pg.no_join ${joinName}`);
402
+ const { idCol, schema } = options;
403
+ const joinOptions = options.joins[joinName];
404
+ const { table: joinTable, refCol } = options.joins[joinName];
405
+ return sql`"${raw(idCol)}" IN (SELECT "${raw(refCol)}"::${raw(
406
+ schema.types[idCol]
407
+ )} FROM "${raw(joinTable)}" WHERE ${getNodeSql(ast[2], joinOptions)})`;
408
+ }
409
+ const [prefix, ...suffix] = ast[1].split(".");
410
+ const { types: types2 = {} } = options.schema;
411
+ if (!types2[prefix])
412
+ throw Error(`pg.no_column ${prefix}`);
413
+ if (types2[prefix] === "jsonb") {
414
+ const [lhs, textLhs] = suffix.length ? [
415
+ sql`"${raw(prefix)}" #> ${suffix}`,
416
+ sql`"${raw(prefix)}" #>> ${suffix}`
417
+ ] : [sql`"${raw(prefix)}"`, sql`"${raw(prefix)}" #>> '{}'`];
418
+ return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
419
+ } else {
420
+ if (suffix.length)
421
+ throw Error(`pg.lookup_not_jsonb ${prefix}`);
422
+ return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
414
423
  }
415
- return getNodeSql(getAst(filter));
424
+ }
425
+ function getSql(filter, options) {
426
+ const ast = getAst(filter);
427
+ return getNodeSql(ast, options);
416
428
  }
417
429
  const getIdMeta = ({ idCol, verDefault }) => sql`"${raw(idCol)}" AS "$key", ${raw(verDefault)} AS "$ver"`;
418
430
  const getArgMeta = (key, { prefix, idCol, verDefault }) => sql`
@@ -440,7 +452,12 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
440
452
  if (!isEmpty(filter))
441
453
  where.push(getSql(filter, options));
442
454
  if (!hasRangeArg)
443
- return { meta: meta(baseKey), where, limit: 1 };
455
+ return {
456
+ meta: meta(baseKey),
457
+ where,
458
+ limit: 1,
459
+ ensureSingleRow: $group === true
460
+ };
444
461
  const groupCols = Array.isArray($group) && $group.length && $group.map((prop) => lookup(prop, options));
445
462
  const group = groupCols ? join(groupCols, ", ") : void 0;
446
463
  const orderCols = ($order || [idCol]).map(
@@ -467,7 +484,8 @@ function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $curs
467
484
  where,
468
485
  order,
469
486
  group,
470
- limit: $first || $last
487
+ limit: $first || $last,
488
+ ensureSingleRow: true
471
489
  };
472
490
  }
473
491
  function getBoundCond(orderCols, bound, kind) {
@@ -501,9 +519,23 @@ function getBoundCond(orderCols, bound, kind) {
501
519
  }
502
520
  const MAX_LIMIT = 4096;
503
521
  function selectByArgs(args, projection, options) {
504
- const { table } = options;
505
- const { where, order, group, limit, meta } = getArgSql(args, options);
522
+ const { table, idCol } = options;
523
+ const { where, order, group, limit, meta, ensureSingleRow } = getArgSql(
524
+ args,
525
+ options
526
+ );
506
527
  const clampedLimit = Math.min(MAX_LIMIT, limit || MAX_LIMIT);
528
+ if (!ensureSingleRow) {
529
+ return sql`
530
+ SELECT
531
+ ${getSelectCols(options, projection)}, ${meta}
532
+ FROM "${raw(table)}" WHERE "${raw(idCol)}" = (
533
+ SELECT "${raw(idCol)}" FROM "${raw(table)}"
534
+ ${where.length ? sql`WHERE ${join(where, " AND ")}` : empty}
535
+ LIMIT 2
536
+ )
537
+ `;
538
+ }
507
539
  return sql`
508
540
  SELECT
509
541
  ${getSelectCols(options, projection)}, ${meta}
@@ -539,7 +571,7 @@ function getSingleSql(arg, options) {
539
571
  SELECT "${raw(idCol)}"
540
572
  FROM "${raw(table)}"
541
573
  WHERE ${join(where, " AND ")}
542
- LIMIT 1
574
+ LIMIT 2
543
575
  )`,
544
576
  meta
545
577
  };
@@ -636,10 +668,10 @@ class Db {
636
668
  }
637
669
  return res.rows[0];
638
670
  }
639
- async ensureSchema(tableOptions) {
671
+ async ensureSchema(tableOptions, typeOids) {
640
672
  if (tableOptions.schema)
641
673
  return;
642
- const { table, verCol } = tableOptions;
674
+ const { table, verCol, joins } = tableOptions;
643
675
  const tableSchema = (await this.query(sql`
644
676
  SELECT table_schema
645
677
  FROM information_schema.tables
@@ -654,7 +686,7 @@ class Db {
654
686
  table_schema = ${tableSchema}`)).rows[0].column_types;
655
687
  if (!types2)
656
688
  throw Error(`pg.missing_table ${table}`);
657
- const typeOids = (await this.query(sql`
689
+ typeOids = typeOids || (await this.query(sql`
658
690
  SELECT jsonb_object_agg(typname, oid) AS type_oids
659
691
  FROM pg_type
660
692
  WHERE typname = 'cube'`)).rows[0].type_oids;
@@ -668,6 +700,11 @@ class Db {
668
700
  if (!verDefault) {
669
701
  throw Error(`pg.verCol_without_default ${verCol}`);
670
702
  }
703
+ await Promise.all(
704
+ Object.values(joins).map(
705
+ (joinOptions) => this.ensureSchema(joinOptions, typeOids)
706
+ )
707
+ );
671
708
  log("ensureSchema", types2);
672
709
  tableOptions.schema = { types: types2, typeOids };
673
710
  tableOptions.verDefault = verDefault;
@@ -758,18 +795,33 @@ class Db {
758
795
  return result;
759
796
  }
760
797
  }
761
- const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store) => {
762
- store.on("read", read);
763
- store.on("write", write);
764
- const prefix = store.path;
765
- const tableOpts = {
766
- prefix,
767
- table: table || prefix[prefix.length - 1] || "default",
798
+ function getTableOpts(name, { table, idCol, verCol, joins, schema, verDefault } = {}, parentName = null) {
799
+ const tableName = table || name;
800
+ return {
801
+ table: table || name,
768
802
  idCol: idCol || "id",
769
803
  verCol: verCol || "updatedAt",
804
+ joins: Object.fromEntries(
805
+ Object.entries(joins || {}).map(
806
+ ([joinName, { refCol = parentName, ...joinOptions }]) => [
807
+ joinName,
808
+ {
809
+ refCol,
810
+ ...getTableOpts(joinName, joinOptions, tableName)
811
+ }
812
+ ]
813
+ )
814
+ ),
770
815
  schema,
771
816
  verDefault
772
817
  };
818
+ }
819
+ const pg = ({ connection, ...rawOptions }) => (store) => {
820
+ store.on("read", read);
821
+ store.on("write", write);
822
+ const prefix = store.path;
823
+ const tableOpts = getTableOpts(prefix[prefix.length - 1], rawOptions);
824
+ tableOpts.prefix = prefix;
773
825
  const defaultDb = new Db(connection);
774
826
  function read(query, options, next) {
775
827
  const { pgClient } = options;
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.3",
5
+ "version": "0.16.4-alpha.2",
6
6
  "main": "./index.cjs",
7
7
  "exports": {
8
8
  "import": "./index.mjs",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "dependencies": {
19
- "@graffy/common": "0.16.3",
19
+ "@graffy/common": "0.16.4-alpha.2",
20
20
  "debug": "^4.3.3"
21
21
  },
22
22
  "peerDependencies": {
package/types/Db.d.ts CHANGED
@@ -4,7 +4,7 @@ export default class Db {
4
4
  query(sql: any, tableOptions: any): Promise<any>;
5
5
  readSql(sql: any, tableOptions: any): Promise<any>;
6
6
  writeSql(sql: any, tableOptions: any): Promise<any>;
7
- ensureSchema(tableOptions: any): Promise<void>;
7
+ ensureSchema(tableOptions: any, typeOids: any): Promise<void>;
8
8
  read(rootQuery: any, tableOptions: any): Promise<any>;
9
9
  write(rootChange: any, tableOptions: any): Promise<any[]>;
10
10
  }
package/types/index.d.ts CHANGED
@@ -1,8 +1,13 @@
1
- export function pg({ table, idCol, verCol, connection, schema, verDefault }: {
2
- table?: string;
3
- idCol?: string;
4
- verCol?: string;
5
- connection?: any;
1
+ export function pg({ connection, ...rawOptions }: Partial<TableOpts> & {
2
+ connection: any;
3
+ }): Function;
4
+ export type TableOpts = {
5
+ table: string;
6
+ idCol: string;
7
+ verCol: string;
8
+ joins: Record<string, Partial<TableOpts> & {
9
+ refCol: string;
10
+ }>;
6
11
  schema?: any;
7
12
  verDefault?: string;
8
- }): (store: any) => void;
13
+ };
@@ -5,7 +5,7 @@
5
5
  @param {{prefix: string, idCol: string, verDefault: string}} options
6
6
 
7
7
  @typedef { import('sql-template-tag').Sql } Sql
8
- @return {{ meta: Sql, where: Sql[], order?: Sql, group?: Sql, limit: number }}
8
+ @return {{ meta: Sql, where: Sql[], order?: Sql, group?: Sql, limit: number, ensureSingleRow: boolean }}
9
9
  */
10
10
  export default function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $cursor: _, ...rest }: object, options: {
11
11
  prefix: string;
@@ -17,6 +17,7 @@ export default function getArgSql({ $first, $last, $after, $before, $since, $unt
17
17
  order?: Sql;
18
18
  group?: Sql;
19
19
  limit: number;
20
+ ensureSingleRow: boolean;
20
21
  };
21
22
  /**
22
23
  * Uses the args object (typically passed in the $key attribute)