@graffy/pg 0.15.10-alpha.1 → 0.15.11-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.
Files changed (4) hide show
  1. package/Readme.md +0 -39
  2. package/index.cjs +16 -13
  3. package/index.mjs +18 -15
  4. package/package.json +2 -2
package/Readme.md CHANGED
@@ -16,42 +16,3 @@ Connection parameters should be set in environment variables. Uses the [pg](http
16
16
 
17
17
  In this document, _property names_ and _paths_ refer to the structures in the Graffy graph objects, _columns_ refer to Postgres table columns and _args_ refer to structures in the filtering and pagination arguments of Graffy query objects.
18
18
 
19
- - **table**, the name of the PostgreSQL table
20
- - **columns**, an object with column names as keys and an objects describing each column as value. Each descriptor object contains a mandatory **role** property, which may be:
21
-
22
- - **primary**, for the primary key column of this table. There must be exactly one primary column.
23
- - **simple**, for a normal column, which stores the value of a particular property of this object.
24
- - **default**, for a JSON column where all data that isn't mapped to another column is placed. There may be zero or one default column.
25
- - **version**, for a numeric column used to store the version number of the object. There must be exactly one version column.
26
- - **gin**, for a JSONB column into which some properties are copied, for enabling filtering and sorting using that property.
27
- - **tsv**, for an indexed tsvector column for full text searches
28
- - **trgm**, for a trigram-indexed text column for typeahead searches
29
-
30
- The descriptor object may also have the following additional properties.
31
-
32
- - **prop**, the property name or path that maps to this column. Valid for **simple** and **primary** columns. Defaults to the name of the column.
33
- - **props**, an array of property names or paths to copy into a **gin**, **tsv** or **trgm** column. Mandatory for these columns.
34
- - **arg**, the filter argument for querying a **tsv** or **trgm** column. Defaults to the column name.
35
-
36
- - **links**, an object with props as keys and link templates as values. The
37
- link template is an array of strings and objects, which may contain at any _value_ position (including inside the object) a string `$$` followed by a property name. This string will be replaced with a value of that property in this object.
38
- - **pollInterval**, the interval at which the table is polled, for watch.
39
-
40
- ```js
41
- {
42
- table: string, // the name of the PostgreSQL table
43
- columns: {
44
- [columnName]: {
45
- role: 'primary' | 'simple' | 'default' |
46
- 'version' | 'gin' | 'tsv' | 'trgm',
47
- prop: string // primary or simple only
48
- props: string[] // gin, tsv or trgm only
49
- arg: string // tsv or trgm only
50
- }
51
- },
52
- links: {
53
- [prop]: string | (string|object)[]
54
- }
55
- pollInterval: number
56
- }
57
- ```
package/index.cjs CHANGED
@@ -185,10 +185,10 @@ function getCompatibleTypes(value) {
185
185
  return "text";
186
186
  }
187
187
  function getSql(filter, getLookupSql, getColumnType = defaultColumnType) {
188
- function lookup(string) {
188
+ function lookup(string, type) {
189
189
  if (string.substr(0, 3) === "el$")
190
190
  return sql__default["default"]`"${sql.raw(string)}"`;
191
- return getLookupSql(string);
191
+ return getLookupSql(string, type);
192
192
  }
193
193
  function binop(op, left, right) {
194
194
  const lType = left.substr(0, 3) === "el$" ? "any" : getColumnType(left);
@@ -196,7 +196,7 @@ function getSql(filter, getLookupSql, getColumnType = defaultColumnType) {
196
196
  if (lType === "any" || rType === "any" || rType === lType) {
197
197
  return sql__default["default"]`${lookup(left)} ${sql.raw(op)} ${right}`;
198
198
  } else {
199
- return sql__default["default"]`(${lookup(left)})::${sql.raw(rType)} ${sql.raw(op)} ${right}`;
199
+ return sql__default["default"]`(${lookup(left, rType)})::${sql.raw(rType)} ${sql.raw(op)} ${right}`;
200
200
  }
201
201
  }
202
202
  function getNodeSql(ast) {
@@ -269,7 +269,7 @@ const getJsonBuildValue = (value) => {
269
269
  return value;
270
270
  if (typeof value === "string")
271
271
  return sql__default["default"]`${value}::text`;
272
- return sql__default["default"]`${stripAttributes(value)}::jsonb`;
272
+ return sql__default["default"]`${JSON.stringify(stripAttributes(value))}::jsonb`;
273
273
  };
274
274
  const getSelectCols = (table) => {
275
275
  return sql__default["default"]`to_jsonb("${sql.raw(table)}")`;
@@ -279,13 +279,13 @@ const getInsert = (row, options) => {
279
279
  const vals = [];
280
280
  Object.entries(row).filter(([name]) => name !== options.verCol && name[0] !== "$").concat([[options.verCol, nowTimestamp]]).forEach(([col, val]) => {
281
281
  cols.push(sql__default["default"]`"${sql.raw(col)}"`);
282
- vals.push(val instanceof sql.Sql ? val : stripAttributes(val));
282
+ vals.push(val instanceof sql.Sql || typeof val !== "object" || !val ? val : sql__default["default"]`${JSON.stringify(stripAttributes(val))}::jsonb`);
283
283
  });
284
284
  return { cols: sql.join(cols, ", "), vals: sql.join(vals, ", ") };
285
285
  };
286
286
  const getUpdates = (row, options) => {
287
287
  return sql.join(Object.entries(row).filter(([name]) => name !== options.idCol && name[0] !== "$").map(([name, value]) => {
288
- return sql__default["default"]`"${sql.raw(name)}" = ${typeof value === "object" && value && !value.$put ? sql__default["default"]`jsonb_strip_nulls(${getJsonUpdate(value, name, [])})` : stripAttributes(value)}`;
288
+ return sql__default["default"]`"${sql.raw(name)}" = ${value instanceof sql.Sql || typeof value !== "object" || !value ? value : !value.$put ? sql__default["default"]`jsonb_strip_nulls(${getJsonUpdate(value, name, [])})` : sql__default["default"]`${JSON.stringify(stripAttributes(value))}::jsonb`}`;
289
289
  }).concat(sql__default["default"]`"${sql.raw(options.verCol)}" = ${nowTimestamp}`), ", ");
290
290
  };
291
291
  function getJsonUpdate(_a, col, path) {
@@ -304,14 +304,14 @@ function stripAttributes(object) {
304
304
  if (typeof object !== "object" || !object)
305
305
  return object;
306
306
  if (Array.isArray(object)) {
307
- return JSON.stringify(object.map((item) => stripAttributes(item)));
307
+ return object.map((item) => stripAttributes(item));
308
308
  }
309
- return JSON.stringify(Object.entries(object).reduce((out, [key, val]) => {
309
+ return Object.entries(object).reduce((out, [key, val]) => {
310
310
  if (key === "$put")
311
311
  return out;
312
312
  out[key] = stripAttributes(val);
313
313
  return out;
314
- }, {}));
314
+ }, {});
315
315
  }
316
316
  const getIdMeta = ({ idCol }) => getJsonBuildObject({
317
317
  $key: sql__default["default"]`"${sql.raw(idCol)}"`,
@@ -326,9 +326,10 @@ function getArgSql(_c, options) {
326
326
  var _d = _c, { $first, $last, $after, $before, $since, $until, $all, $cursor: _ } = _d, rest = __objRest(_d, ["$first", "$last", "$after", "$before", "$since", "$until", "$all", "$cursor"]);
327
327
  const _a = rest, { $order } = _a, filter = __objRest(_a, ["$order"]);
328
328
  const { prefix, idCol } = options;
329
- const lookup = (prop) => {
329
+ const lookup = (prop, type) => {
330
330
  const [prefix2, ...suffix] = common.encodePath(prop);
331
- return suffix.length ? sql__default["default"]`"${sql.raw(prefix2)}" #> ${suffix}` : sql__default["default"]`"${sql.raw(prefix2)}"`;
331
+ const op = type === "text" ? sql__default["default"]`#>>` : sql__default["default"]`#>`;
332
+ return suffix.length ? sql__default["default"]`"${sql.raw(prefix2)}" ${op} ${suffix}` : sql__default["default"]`"${sql.raw(prefix2)}"`;
332
333
  };
333
334
  const getType = (prop) => {
334
335
  const [_prefix, ...suffix] = common.encodePath(prop);
@@ -525,7 +526,7 @@ class Db {
525
526
  promises.push(getByIds());
526
527
  await Promise.all(promises);
527
528
  log("dbRead", rootQuery, results);
528
- return common.slice(common.finalize(results, rootQuery), rootQuery).known || [];
529
+ return common.slice(common.finalize(results, common.wrap(query, prefix)), rootQuery).known || [];
529
530
  }
530
531
  async write(rootChange, tableOptions) {
531
532
  const sqls = [];
@@ -582,7 +583,9 @@ const pg = ({ table, idCol, verCol, links, connection }) => (store) => {
582
583
  const writePromise = transactionDb.write(change, tableOpts, writeOpts);
583
584
  const remainingChange = common.remove(change, prefix);
584
585
  const nextPromise = next(remainingChange);
585
- return Promise.all([writePromise, nextPromise]).then(([writeRes, nextRes]) => common.merge(writeRes, nextRes));
586
+ return Promise.all([writePromise, nextPromise]).then(([writeRes, nextRes]) => {
587
+ return common.merge(writeRes, nextRes);
588
+ });
586
589
  }
587
590
  };
588
591
  exports.pg = pg;
package/index.mjs CHANGED
@@ -26,9 +26,9 @@ var __objRest = (source, exclude) => {
26
26
  }
27
27
  return target;
28
28
  };
29
- import { isEmpty, encodePath, isPlainObject, unwrap, decodeArgs, slice, finalize, isRange, decodeGraph, mergeObject, merge, encodeGraph, wrapObject, remove } from "@graffy/common";
29
+ import { isEmpty, encodePath, isPlainObject, unwrap, decodeArgs, slice, finalize, wrap, isRange, decodeGraph, mergeObject, merge, encodeGraph, wrapObject, remove } from "@graffy/common";
30
30
  import { Pool, Client } from "pg";
31
- import sql, { join, raw, empty, Sql } from "sql-template-tag";
31
+ import sql, { join, raw, Sql, empty } from "sql-template-tag";
32
32
  import debug from "debug";
33
33
  const valid = {
34
34
  $eq: true,
@@ -177,10 +177,10 @@ function getCompatibleTypes(value) {
177
177
  return "text";
178
178
  }
179
179
  function getSql(filter, getLookupSql, getColumnType = defaultColumnType) {
180
- function lookup(string) {
180
+ function lookup(string, type) {
181
181
  if (string.substr(0, 3) === "el$")
182
182
  return sql`"${raw(string)}"`;
183
- return getLookupSql(string);
183
+ return getLookupSql(string, type);
184
184
  }
185
185
  function binop(op, left, right) {
186
186
  const lType = left.substr(0, 3) === "el$" ? "any" : getColumnType(left);
@@ -188,7 +188,7 @@ function getSql(filter, getLookupSql, getColumnType = defaultColumnType) {
188
188
  if (lType === "any" || rType === "any" || rType === lType) {
189
189
  return sql`${lookup(left)} ${raw(op)} ${right}`;
190
190
  } else {
191
- return sql`(${lookup(left)})::${raw(rType)} ${raw(op)} ${right}`;
191
+ return sql`(${lookup(left, rType)})::${raw(rType)} ${raw(op)} ${right}`;
192
192
  }
193
193
  }
194
194
  function getNodeSql(ast) {
@@ -261,7 +261,7 @@ const getJsonBuildValue = (value) => {
261
261
  return value;
262
262
  if (typeof value === "string")
263
263
  return sql`${value}::text`;
264
- return sql`${stripAttributes(value)}::jsonb`;
264
+ return sql`${JSON.stringify(stripAttributes(value))}::jsonb`;
265
265
  };
266
266
  const getSelectCols = (table) => {
267
267
  return sql`to_jsonb("${raw(table)}")`;
@@ -271,13 +271,13 @@ const getInsert = (row, options) => {
271
271
  const vals = [];
272
272
  Object.entries(row).filter(([name]) => name !== options.verCol && name[0] !== "$").concat([[options.verCol, nowTimestamp]]).forEach(([col, val]) => {
273
273
  cols.push(sql`"${raw(col)}"`);
274
- vals.push(val instanceof Sql ? val : stripAttributes(val));
274
+ vals.push(val instanceof Sql || typeof val !== "object" || !val ? val : sql`${JSON.stringify(stripAttributes(val))}::jsonb`);
275
275
  });
276
276
  return { cols: join(cols, ", "), vals: join(vals, ", ") };
277
277
  };
278
278
  const getUpdates = (row, options) => {
279
279
  return join(Object.entries(row).filter(([name]) => name !== options.idCol && name[0] !== "$").map(([name, value]) => {
280
- return sql`"${raw(name)}" = ${typeof value === "object" && value && !value.$put ? sql`jsonb_strip_nulls(${getJsonUpdate(value, name, [])})` : stripAttributes(value)}`;
280
+ return sql`"${raw(name)}" = ${value instanceof Sql || typeof value !== "object" || !value ? value : !value.$put ? sql`jsonb_strip_nulls(${getJsonUpdate(value, name, [])})` : sql`${JSON.stringify(stripAttributes(value))}::jsonb`}`;
281
281
  }).concat(sql`"${raw(options.verCol)}" = ${nowTimestamp}`), ", ");
282
282
  };
283
283
  function getJsonUpdate(_a, col, path) {
@@ -296,14 +296,14 @@ function stripAttributes(object) {
296
296
  if (typeof object !== "object" || !object)
297
297
  return object;
298
298
  if (Array.isArray(object)) {
299
- return JSON.stringify(object.map((item) => stripAttributes(item)));
299
+ return object.map((item) => stripAttributes(item));
300
300
  }
301
- return JSON.stringify(Object.entries(object).reduce((out, [key, val]) => {
301
+ return Object.entries(object).reduce((out, [key, val]) => {
302
302
  if (key === "$put")
303
303
  return out;
304
304
  out[key] = stripAttributes(val);
305
305
  return out;
306
- }, {}));
306
+ }, {});
307
307
  }
308
308
  const getIdMeta = ({ idCol }) => getJsonBuildObject({
309
309
  $key: sql`"${raw(idCol)}"`,
@@ -318,9 +318,10 @@ function getArgSql(_c, options) {
318
318
  var _d = _c, { $first, $last, $after, $before, $since, $until, $all, $cursor: _ } = _d, rest = __objRest(_d, ["$first", "$last", "$after", "$before", "$since", "$until", "$all", "$cursor"]);
319
319
  const _a = rest, { $order } = _a, filter = __objRest(_a, ["$order"]);
320
320
  const { prefix, idCol } = options;
321
- const lookup = (prop) => {
321
+ const lookup = (prop, type) => {
322
322
  const [prefix2, ...suffix] = encodePath(prop);
323
- return suffix.length ? sql`"${raw(prefix2)}" #> ${suffix}` : sql`"${raw(prefix2)}"`;
323
+ const op = type === "text" ? sql`#>>` : sql`#>`;
324
+ return suffix.length ? sql`"${raw(prefix2)}" ${op} ${suffix}` : sql`"${raw(prefix2)}"`;
324
325
  };
325
326
  const getType = (prop) => {
326
327
  const [_prefix, ...suffix] = encodePath(prop);
@@ -517,7 +518,7 @@ class Db {
517
518
  promises.push(getByIds());
518
519
  await Promise.all(promises);
519
520
  log("dbRead", rootQuery, results);
520
- return slice(finalize(results, rootQuery), rootQuery).known || [];
521
+ return slice(finalize(results, wrap(query, prefix)), rootQuery).known || [];
521
522
  }
522
523
  async write(rootChange, tableOptions) {
523
524
  const sqls = [];
@@ -574,7 +575,9 @@ const pg = ({ table, idCol, verCol, links, connection }) => (store) => {
574
575
  const writePromise = transactionDb.write(change, tableOpts, writeOpts);
575
576
  const remainingChange = remove(change, prefix);
576
577
  const nextPromise = next(remainingChange);
577
- return Promise.all([writePromise, nextPromise]).then(([writeRes, nextRes]) => merge(writeRes, nextRes));
578
+ return Promise.all([writePromise, nextPromise]).then(([writeRes, nextRes]) => {
579
+ return merge(writeRes, nextRes);
580
+ });
578
581
  }
579
582
  };
580
583
  export { pg };
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.15.10-alpha.1",
5
+ "version": "0.15.11-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.15.10-alpha.1",
19
+ "@graffy/common": "0.15.11-alpha.2",
20
20
  "pg": "^8.7.1",
21
21
  "debug": "^4.3.2",
22
22
  "sql-template-tag": "^4.0.0"