@nuxodin/item 0.6.9 → 0.6.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxodin/item",
3
- "version": "0.6.9",
3
+ "version": "0.6.11",
4
4
  "description": "Reactive state library",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/tools/db/sql.d.ts CHANGED
@@ -10,6 +10,8 @@ export interface SqlTag {
10
10
  id(name: string | { toString(): string } | Promise<string | { toString(): string }>): Sql;
11
11
  raw(text: string): Sql;
12
12
  join(frags: Sql[], separator?: string): Sql;
13
+ in(col: string | Sql, values: Iterable<unknown>): Sql;
14
+ notIn(col: string | Sql, values: Iterable<unknown>): Sql;
13
15
  }
14
16
 
15
17
  export const sql: SqlTag;
package/tools/db/sql.js CHANGED
@@ -38,6 +38,26 @@ sql.join = (frags, separator = ', ') => {
38
38
  return new Sql(parts);
39
39
  };
40
40
 
41
+ /** A column: a name is quoted per dialect, `a.b` in its parts; anything else is a fragment already. */
42
+ const column = (c) => typeof c === 'string' ? sql.join(c.split('.').map(n => sql.id(n)), '.') : c;
43
+
44
+ /**
45
+ * `x IN (…)`, and a plain `false` where there is nothing to be in — `IN ()` is a syntax error, and
46
+ * an empty subquery cannot be typed for every column (`IN (SELECT NULL WHERE FALSE)` is a type
47
+ * error in postgres). The column belongs inside for exactly that reason: only there can the empty
48
+ * case be a boolean instead of a comparison.
49
+ */
50
+ sql.in = (col, values) => {
51
+ const list = [...values];
52
+ return list.length ? sql`${column(col)} IN (${sql.join(list.map(v => sql`${v}`))})` : sql.raw('false');
53
+ };
54
+
55
+ /** The other way round — and nothing to be in means everything qualifies. */
56
+ sql.notIn = (col, values) => {
57
+ const list = [...values];
58
+ return list.length ? sql`${column(col)} NOT IN (${sql.join(list.map(v => sql`${v}`))})` : sql.raw('true');
59
+ };
60
+
41
61
  // Objects with their own toString bind as strings; plain objects/arrays are
42
62
  // mistakes (drivers would mangle them, e.g. mysql2's `key`='value' expansion).
43
63
  function toParam(v) {
@@ -37,12 +37,12 @@ export function schemaFromField(row) {
37
37
  } else if (type === 'date') {
38
38
  prop.type = 'string'
39
39
  prop.format = 'date'
40
- } else if (type.startsWith('time') || dataType.startsWith('time')) {
41
- prop.type = 'string'
42
- prop.format = 'time'
43
40
  } else if (type.startsWith('timestamp') || dataType.startsWith('timestamp')) {
44
41
  prop.type = 'string'
45
42
  prop.format = 'date-time'
43
+ } else if (type.startsWith('time') || dataType.startsWith('time')) {
44
+ prop.type = 'string'
45
+ prop.format = 'time'
46
46
  } else if (type === 'json' || type === 'jsonb') prop.type = 'object'
47
47
  else prop.type = 'string'
48
48
 
@@ -50,7 +50,7 @@ function createIndex(table, name, kind) {
50
50
 
51
51
  async function tableIndexes(query, table) {
52
52
  const primaryRows = await queryRows(query, `
53
- SELECT con.conname, array_agg(a.attname ORDER BY u.ord) AS columns
53
+ SELECT con.conname, json_agg(a.attname ORDER BY u.ord) AS columns
54
54
  FROM pg_constraint con
55
55
  JOIN pg_class t ON t.oid = con.conrelid
56
56
  JOIN pg_namespace n ON n.oid = t.relnamespace