@thi.ng/oquery 2.2.9 → 2.2.10

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/README.md CHANGED
@@ -79,7 +79,7 @@ For Node.js REPL:
79
79
  const oquery = await import("@thi.ng/oquery");
80
80
  ```
81
81
 
82
- Package sizes (brotli'd, pre-treeshake): ESM: 1.66 KB
82
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.67 KB
83
83
 
84
84
  ## Dependencies
85
85
 
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/match.js CHANGED
@@ -1,169 +1,79 @@
1
1
  import { isNumber } from "@thi.ng/checks/is-number";
2
2
  import { isString } from "@thi.ng/checks/is-string";
3
3
  import { numericOp, stringOp } from "@thi.ng/compare";
4
- /**
5
- * Syntax sugar for {@link matchMultiple} using string arrays. Matches set of
6
- * given strings against an item's chosen field of strings and by default only
7
- * succeeds if all provided strings can be matched.
8
- *
9
- * @remarks
10
- * Any provided string prefixed with `!` is treated as an exclusion and any item
11
- * which contains any of these exclusions is automatically rejected, even if
12
- * other strings could be matched.
13
- *
14
- * See {@link matchMultiple} for more details & code example.
15
- *
16
- * @param key
17
- * @param matches
18
- * @param opts
19
- * @returns
20
- */
21
- export const matchStrings = (key, matches, opts) => {
22
- const [includes, excludes] = matches.reduce((acc, x) => {
23
- x[0] === "!" ? acc[1].push(x.substring(1)) : acc[0].push(x);
24
- return acc;
25
- }, [[], []]);
26
- return matchMultiple(key, includes, excludes, opts);
4
+ const matchStrings = (key, matches, opts) => {
5
+ const [includes, excludes] = matches.reduce(
6
+ (acc, x) => {
7
+ x[0] === "!" ? acc[1].push(x.substring(1)) : acc[0].push(x);
8
+ return acc;
9
+ },
10
+ [[], []]
11
+ );
12
+ return matchMultiple(key, includes, excludes, opts);
27
13
  };
28
- /**
29
- * Returns a {@link QueryTerm} for use with {@link query} to perform set-like
30
- * intersection or union queries with optional negation/exclusions. Matches set
31
- * of given values against an item's chosen field of values and by default only
32
- * succeeds if all provided `includes` can be matched (aka intersection query)
33
- * and there're no values from `excludes` present.
34
- *
35
- * @remarks
36
- * If the `union` option is true, only one of the provided values needs to
37
- * match. Exclusions _always_ take precedence.
38
- *
39
- * Note: See {@link matchStrings} for a syntax sugar of this function, aimed at
40
- * matching `string[]` options.
41
- *
42
- * @example
43
- * ```ts
44
- * const DB = [
45
- * { id: 1, tags: ["a", "b"] },
46
- * { id: 2, tags: ["c", "b"] },
47
- * { id: 3, tags: ["c", "a"] },
48
- * ];
49
- *
50
- * // tag intersection
51
- * query(DB, [matchStrings("tags", ["a", "b"])])
52
- * // [ { id: 1, tags: ["a", "b"] } ]
53
- *
54
- * // tag union
55
- * query(DB, [matchStrings("tags", ["a", "b"])])
56
- * // here returns full DB...
57
- * // since each item either has `a` and/or `b` tags
58
- *
59
- * // tag exclusion (require `a`, disallow `b`)
60
- * query(DB, [matchStrings("tags", ["a", "!b"])])
61
- * // [ { id: 3, tags: ["c", "a"] } ]
62
- * ```
63
- *
64
- * @param key
65
- * @param matches
66
- * @param opts
67
- */
68
- export const matchMultiple = (key, includes, excludes, opts) => {
69
- const { union, value: valueFn } = { union: false, ...opts };
70
- return excludes.length
71
- ? {
72
- q: [
73
- key,
74
- (values) => {
75
- const $values = valueFn ? valueFn(values) : values;
76
- for (let x of excludes) {
77
- if ($values.includes(x))
78
- return false;
79
- }
80
- let match = false;
81
- for (let x of includes) {
82
- if ($values.includes(x)) {
83
- match = true;
84
- if (union)
85
- break;
86
- }
87
- else if (!union) {
88
- match = false;
89
- break;
90
- }
91
- }
92
- return match;
93
- },
94
- ],
95
- opts: { cwise: false },
14
+ const matchMultiple = (key, includes, excludes, opts) => {
15
+ const { union, value: valueFn } = { union: false, ...opts };
16
+ return excludes.length ? {
17
+ q: [
18
+ key,
19
+ (values) => {
20
+ const $values = valueFn ? valueFn(values) : values;
21
+ for (let x of excludes) {
22
+ if ($values.includes(x))
23
+ return false;
96
24
  }
97
- : { q: [key, includes], opts: { intersect: !union } };
98
- };
99
- /**
100
- * Returns a {@link QueryTerm} to match a key's value against a regexp or string
101
- * expression.
102
- *
103
- * @remarks
104
- * If `expr` is a regexp it will be used as is, but if given a string the
105
- * following rules apply:
106
- *
107
- * - if `expr` is the sole `*` it will match any non-null value
108
- * - if `expr` starts with `=`, `!=`, `<`, `<=`, `>=` or `>`, values will be
109
- * matched using comparators. If the following chars in `expr` are numeric,
110
- * the comparisons will be done as numbers otherwise as strings. Whitespace
111
- * between operator and value are ignored.
112
- *
113
- * @example
114
- * ```ts
115
- * const DB = [
116
- * { id: "aaa", score: 32 },
117
- * { id: "bbbb", score: 60 },
118
- * { id: "c", score: 15 },
119
- * ];
120
- *
121
- * query(DB, [matchPattern("id", /[a-z]{4,}/)]);
122
- * // [{ id: "bbbb", score: 60 }]
123
- * query(DB, [matchPattern("id", ">= c")]);
124
- * // [{ id: "c", score: 15 }]
125
- *
126
- * query(DB, [matchPattern("score", "<50")]);
127
- * // [{ id: "a", score: 32 }, { id: "c", score: 15 }]
128
- * ```
129
- *
130
- * @param key
131
- * @param expr
132
- * @param opts
133
- */
134
- export const matchPattern = (key, expr, opts) => {
135
- let re;
136
- if (expr instanceof RegExp) {
137
- re = expr;
138
- }
139
- else {
140
- if (expr === "*")
141
- return { q: [key, (x) => x != null], opts };
142
- if (/^[<>=!]/.test(expr)) {
143
- const op = /^[<>=!]+/.exec(expr)[0];
144
- const arg = expr.substring(op.length).trim();
145
- const argN = parseFloat(arg);
146
- return matchCompare(key, op, isNaN(argN) ? arg : argN, opts);
25
+ let match = false;
26
+ for (let x of includes) {
27
+ if ($values.includes(x)) {
28
+ match = true;
29
+ if (union)
30
+ break;
31
+ } else if (!union) {
32
+ match = false;
33
+ break;
34
+ }
147
35
  }
148
- re = new RegExp(expr, "i");
36
+ return match;
37
+ }
38
+ ],
39
+ opts: { cwise: false }
40
+ } : { q: [key, includes], opts: { intersect: !union } };
41
+ };
42
+ const matchPattern = (key, expr, opts) => {
43
+ let re;
44
+ if (expr instanceof RegExp) {
45
+ re = expr;
46
+ } else {
47
+ if (expr === "*")
48
+ return { q: [key, (x) => x != null], opts };
49
+ if (/^[<>=!]/.test(expr)) {
50
+ const op = /^[<>=!]+/.exec(expr)[0];
51
+ const arg = expr.substring(op.length).trim();
52
+ const argN = parseFloat(arg);
53
+ return matchCompare(
54
+ key,
55
+ op,
56
+ isNaN(argN) ? arg : argN,
57
+ opts
58
+ );
149
59
  }
150
- return {
151
- q: [
152
- key,
153
- (x) => (isString(x) || isNumber(x)) && re.test(String(x)),
154
- ],
155
- opts,
156
- };
60
+ re = new RegExp(expr, "i");
61
+ }
62
+ return {
63
+ q: [
64
+ key,
65
+ (x) => (isString(x) || isNumber(x)) && re.test(String(x))
66
+ ],
67
+ opts
68
+ };
157
69
  };
158
- /**
159
- * Same as the comparison expression case of {@link matchPattern}, only
160
- * accepting different args.
161
- *
162
- * @param key
163
- * @param match
164
- * @param opts
165
- */
166
- export const matchCompare = (key, op, arg, opts) => ({
167
- q: [key, isNumber(arg) ? numericOp(op, arg) : stringOp(op, arg)],
168
- opts,
70
+ const matchCompare = (key, op, arg, opts) => ({
71
+ q: [key, isNumber(arg) ? numericOp(op, arg) : stringOp(op, arg)],
72
+ opts
169
73
  });
74
+ export {
75
+ matchCompare,
76
+ matchMultiple,
77
+ matchPattern,
78
+ matchStrings
79
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/oquery",
3
- "version": "2.2.9",
3
+ "version": "2.2.10",
4
4
  "description": "Datalog-inspired, optimized pattern/predicate query engine for JS objects & arrays of objects",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,14 +35,15 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.11",
37
- "@thi.ng/checks": "^3.4.11",
38
- "@thi.ng/compare": "^2.2.7",
39
- "@thi.ng/defmulti": "^3.0.9",
40
- "@thi.ng/equiv": "^2.1.36"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/checks": "^3.4.12",
40
+ "@thi.ng/compare": "^2.2.8",
41
+ "@thi.ng/defmulti": "^3.0.10",
42
+ "@thi.ng/equiv": "^2.1.37"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@microsoft/api-extractor": "^7.38.3",
46
+ "esbuild": "^0.19.8",
44
47
  "rimraf": "^5.0.5",
45
48
  "tools": "^0.0.1",
46
49
  "typedoc": "^0.25.4",
@@ -93,5 +96,5 @@
93
96
  ],
94
97
  "year": 2020
95
98
  },
96
- "gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n"
99
+ "gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
97
100
  }
package/query.js CHANGED
@@ -6,428 +6,336 @@ import { compareByKey } from "@thi.ng/compare/keys";
6
6
  import { reverse } from "@thi.ng/compare/reverse";
7
7
  import { defmulti } from "@thi.ng/defmulti/defmulti";
8
8
  import { equiv } from "@thi.ng/equiv";
9
- /**
10
- * Classifies a single S,P,O term. See {@link QueryType} for explanations.
11
- *
12
- * @param x -
13
- *
14
- * @internal
15
- */
16
- const classify = (x) => (x != null ? (isFunction(x) ? "f" : "l") : "n");
17
- /** @internal */
18
- const ensureArray = (src) => (isArray(src) ? src : [...src]);
19
- /** @internal */
9
+ const classify = (x) => x != null ? isFunction(x) ? "f" : "l" : "n";
10
+ const ensureArray = (src) => isArray(src) ? src : [...src];
20
11
  const ensureSet = (src) => isArray(src) ? new Set(src) : src;
21
- /**
22
- * HOF predicate function for intersection queries (i.e. iff `opts.intersect =
23
- * true`). Takes an array or set query term and returns predicate to check if
24
- * ALL of the query term elements are present in a given object (assumed to be
25
- * an array or set too).
26
- *
27
- * @param src -
28
- *
29
- * @internal
30
- */
31
12
  const intersect = (src) => {
32
- const a = ensureArray(src);
33
- const num = a.length;
34
- return (b) => {
35
- const $b = ensureSet(b);
36
- for (let i = num; i-- > 0;) {
37
- if (!$b.has(a[i]))
38
- return false;
39
- }
40
- return true;
41
- };
13
+ const a = ensureArray(src);
14
+ const num = a.length;
15
+ return (b) => {
16
+ const $b = ensureSet(b);
17
+ for (let i = num; i-- > 0; ) {
18
+ if (!$b.has(a[i]))
19
+ return false;
20
+ }
21
+ return true;
22
+ };
42
23
  };
43
- /**
44
- * Checks the type of a single S,P,O term and if an array or Set, returns a
45
- * predicate function to check if an element is included. Otherwise, returns
46
- * input. If `isec` is true, the returned predicate will be the result of
47
- * {@link intersect}.
48
- *
49
- * @param x -
50
- * @param isec -
51
- *
52
- * @internal
53
- */
54
- const coerce = (x, isec = false) => isArray(x)
55
- ? isec
56
- ? intersect(x)
57
- : (y) => x.includes(y)
58
- : isSet(x)
59
- ? isec
60
- ? intersect(x)
61
- : (y) => x.has(y)
62
- : x;
63
- /**
64
- * Similar to {@link coerce}, but intended for S,P terms. Unless `x` is a
65
- * function or null, coerces `x` (or its elements) to strings first.
66
- *
67
- * @param x -
68
- *
69
- * @internal
70
- */
71
- const coerceStr = (x) => isArray(x)
72
- ? coerce(x.map((y) => String(y)))
73
- : isSet(x)
74
- ? coerce(new Set([...x].map((y) => String(y))))
75
- : x == null || isFunction(x)
76
- ? x
77
- : String(x);
24
+ const coerce = (x, isec = false) => isArray(x) ? isec ? intersect(x) : (y) => x.includes(y) : isSet(x) ? isec ? intersect(x) : (y) => x.has(y) : x;
25
+ const coerceStr = (x) => isArray(x) ? coerce(x.map((y) => String(y))) : isSet(x) ? coerce(new Set([...x].map((y) => String(y)))) : x == null || isFunction(x) ? x : String(x);
78
26
  const addTriple = (acc, s, p, o) => {
79
- const sval = acc[s];
80
- sval ? (sval[p] = o) : (acc[s] = { [p]: o });
27
+ const sval = acc[s];
28
+ sval ? sval[p] = o : acc[s] = { [p]: o };
81
29
  };
82
30
  const match = (o, val, opts) => {
83
- if (val != null) {
84
- const pred = ((isFunction(o) ? o : ($) => opts.equiv(o, $)));
85
- return opts.cwise && isArray(val) ? val.some(pred) : pred(val);
86
- }
87
- return false;
31
+ if (val != null) {
32
+ const pred = isFunction(o) ? o : ($) => opts.equiv(o, $);
33
+ return opts.cwise && isArray(val) ? val.some(pred) : pred(val);
34
+ }
35
+ return false;
88
36
  };
89
37
  const collect = (acc, s, p, o, val, opts) => {
90
- if (val != null) {
91
- const pred = isFunction(o) ? o : ($) => opts.equiv(o, $);
92
- if (opts.cwise && isArray(val)) {
93
- val = val.filter(pred);
94
- val.length && addTriple(acc, s, p, val);
95
- }
96
- else if (pred(val)) {
97
- addTriple(acc, s, p, val);
98
- }
38
+ if (val != null) {
39
+ const pred = isFunction(o) ? o : ($) => opts.equiv(o, $);
40
+ if (opts.cwise && isArray(val)) {
41
+ val = val.filter(pred);
42
+ val.length && addTriple(acc, s, p, val);
43
+ } else if (pred(val)) {
44
+ addTriple(acc, s, p, val);
99
45
  }
46
+ }
100
47
  };
101
- const collectFull = (res, s, val) => (res[s] = val);
48
+ const collectFull = (res, s, val) => res[s] = val;
102
49
  const collectSP = (res, sval, s, p, o, opts) => {
103
- if (opts.partial) {
104
- for (let $p in sval) {
105
- p($p) && collect(res, s, $p, o, sval[$p], opts);
106
- }
50
+ if (opts.partial) {
51
+ for (let $p in sval) {
52
+ p($p) && collect(res, s, $p, o, sval[$p], opts);
107
53
  }
108
- else {
109
- for (let $p in sval) {
110
- if (p($p) && match(o, sval[$p], opts)) {
111
- collectFull(res, s, sval);
112
- return;
113
- }
114
- }
54
+ } else {
55
+ for (let $p in sval) {
56
+ if (p($p) && match(o, sval[$p], opts)) {
57
+ collectFull(res, s, sval);
58
+ return;
59
+ }
115
60
  }
61
+ }
116
62
  };
117
63
  const collectSO = (res, sval, s, o, opts) => {
118
- if (opts.partial) {
119
- for (let p in sval) {
120
- collect(res, s, p, o, sval[p], opts);
121
- }
64
+ if (opts.partial) {
65
+ for (let p in sval) {
66
+ collect(res, s, p, o, sval[p], opts);
122
67
  }
123
- else {
124
- for (let p in sval) {
125
- if (match(o, sval[p], opts)) {
126
- collectFull(res, s, sval);
127
- return;
128
- }
129
- }
68
+ } else {
69
+ for (let p in sval) {
70
+ if (match(o, sval[p], opts)) {
71
+ collectFull(res, s, sval);
72
+ return;
73
+ }
130
74
  }
75
+ }
131
76
  };
132
77
  const queryLL = (res, db, s, p, o, opts) => {
133
- const sval = db[s];
134
- const val = sval?.[p];
135
- if (opts.partial) {
136
- collect(res, s, p, o, val, opts);
137
- }
138
- else {
139
- match(o, val, opts) && collectFull(res, s, sval);
140
- }
78
+ const sval = db[s];
79
+ const val = sval?.[p];
80
+ if (opts.partial) {
81
+ collect(res, s, p, o, val, opts);
82
+ } else {
83
+ match(o, val, opts) && collectFull(res, s, sval);
84
+ }
141
85
  };
142
86
  const queryLF = (res, db, s, p, o, opts) => {
143
- const sval = db[s];
144
- sval != null && collectSP(res, sval, s, p, o, opts);
87
+ const sval = db[s];
88
+ sval != null && collectSP(res, sval, s, p, o, opts);
145
89
  };
146
90
  const queryLN = (res, db, s, _, o, opts) => {
147
- const sval = db[s];
148
- sval != null && collectSO(res, sval, s, o, opts);
91
+ const sval = db[s];
92
+ sval != null && collectSO(res, sval, s, o, opts);
149
93
  };
150
94
  const queryFL = (res, db, s, p, o, opts) => {
151
- if (opts.partial) {
152
- for (let $s in db) {
153
- s($s) && collect(res, $s, p, o, db[$s]?.[p], opts);
154
- }
95
+ if (opts.partial) {
96
+ for (let $s in db) {
97
+ s($s) && collect(res, $s, p, o, db[$s]?.[p], opts);
155
98
  }
156
- else {
157
- for (let $s in db) {
158
- const sval = db[$s];
159
- s($s) &&
160
- match(o, sval?.[p], opts) &&
161
- collectFull(res, $s, sval);
162
- }
99
+ } else {
100
+ for (let $s in db) {
101
+ const sval = db[$s];
102
+ s($s) && match(o, sval?.[p], opts) && collectFull(res, $s, sval);
163
103
  }
104
+ }
164
105
  };
165
106
  const queryFF = (res, db, s, p, o, opts) => {
166
- for (let $s in db) {
167
- s($s) && collectSP(res, db[$s], $s, p, o, opts);
168
- }
107
+ for (let $s in db) {
108
+ s($s) && collectSP(res, db[$s], $s, p, o, opts);
109
+ }
169
110
  };
170
111
  const queryFN = (res, db, s, _, o, opts) => {
171
- for (let $s in db) {
172
- s($s) && collectSO(res, db[$s], $s, o, opts);
173
- }
112
+ for (let $s in db) {
113
+ s($s) && collectSO(res, db[$s], $s, o, opts);
114
+ }
174
115
  };
175
116
  const queryNL = (res, db, _, p, o, opts) => {
176
- if (opts.partial) {
177
- for (let s in db) {
178
- collect(res, s, p, o, db[s][p], opts);
179
- }
117
+ if (opts.partial) {
118
+ for (let s in db) {
119
+ collect(res, s, p, o, db[s][p], opts);
180
120
  }
181
- else {
182
- for (let s in db) {
183
- const sval = db[s];
184
- match(o, sval[p], opts) && collectFull(res, s, sval);
185
- }
121
+ } else {
122
+ for (let s in db) {
123
+ const sval = db[s];
124
+ match(o, sval[p], opts) && collectFull(res, s, sval);
186
125
  }
126
+ }
187
127
  };
188
128
  const queryNF = (res, db, _, p, o, opts) => {
189
- for (let s in db) {
190
- collectSP(res, db[s], s, p, o, opts);
191
- }
129
+ for (let s in db) {
130
+ collectSP(res, db[s], s, p, o, opts);
131
+ }
192
132
  };
193
133
  const queryNN = (res, db, _, __, o, opts) => {
194
- for (let s in db) {
195
- collectSO(res, db[s], s, o, opts);
196
- }
134
+ for (let s in db) {
135
+ collectSO(res, db[s], s, o, opts);
136
+ }
197
137
  };
198
138
  const querySP = (res, sval, s, p, _, opts) => {
199
- if (opts.partial) {
200
- for (let q in sval) {
201
- if (p(q)) {
202
- const val = sval[q];
203
- val != null && addTriple(res, s, q, val);
204
- }
205
- }
139
+ if (opts.partial) {
140
+ for (let q in sval) {
141
+ if (p(q)) {
142
+ const val = sval[q];
143
+ val != null && addTriple(res, s, q, val);
144
+ }
206
145
  }
207
- else {
208
- for (let q in sval) {
209
- if (p(q)) {
210
- collectFull(res, s, sval);
211
- return;
212
- }
213
- }
146
+ } else {
147
+ for (let q in sval) {
148
+ if (p(q)) {
149
+ collectFull(res, s, sval);
150
+ return;
151
+ }
214
152
  }
153
+ }
215
154
  };
216
155
  const queryO = (res, db, s, p, _, opts) => {
217
- const sval = db[s];
218
- const val = sval?.[p];
219
- val != null &&
220
- (opts.partial ? addTriple(res, s, p, val) : collectFull(res, s, sval));
156
+ const sval = db[s];
157
+ const val = sval?.[p];
158
+ val != null && (opts.partial ? addTriple(res, s, p, val) : collectFull(res, s, sval));
221
159
  };
222
160
  const IMPLS = {
223
- lll: queryLL,
224
- llf: queryLL,
225
- lln: queryO,
226
- lfl: queryLF,
227
- lff: queryLF,
228
- lfn: (res, db, s, p, _, opts) => {
229
- const sval = db[s];
230
- sval != null && querySP(res, sval, s, p, null, opts);
231
- },
232
- lnl: queryLN,
233
- lnf: queryLN,
234
- lnn: (res, db, s) => {
235
- const sval = db[s];
236
- sval != null && collectFull(res, s, sval);
237
- },
238
- fll: queryFL,
239
- flf: queryFL,
240
- fln: (res, db, s, p, _, opts) => {
241
- for (let $s in db) {
242
- s($s) && queryO(res, db, $s, p, null, opts);
243
- }
244
- },
245
- ffl: queryFF,
246
- fff: queryFF,
247
- ffn: (res, db, s, p, _, opts) => {
248
- if (opts.partial) {
249
- for (let $s in db) {
250
- if (s($s)) {
251
- const sval = db[$s];
252
- for (let $p in sval) {
253
- p($p) && addTriple(res, $s, $p, sval[$p]);
254
- }
255
- }
256
- }
257
- }
258
- else {
259
- for (let $s in db) {
260
- if (s($s)) {
261
- const sval = db[$s];
262
- for (let $p in sval) {
263
- if (p($p)) {
264
- collectFull(res, $s, sval);
265
- break;
266
- }
267
- }
268
- }
269
- }
270
- }
271
- },
272
- fnl: queryFN,
273
- fnf: queryFN,
274
- fnn: (res, db, s) => {
275
- for (let $s in db) {
276
- if (s($s)) {
277
- const sval = db[$s];
278
- sval != null && collectFull(res, $s, sval);
279
- }
280
- }
281
- },
282
- nll: queryNL,
283
- nlf: queryNL,
284
- nln: (res, db, _, p, __, opts) => {
285
- if (opts.partial) {
286
- for (let s in db) {
287
- const val = db[s][p];
288
- val != null && addTriple(res, s, p, val);
289
- }
161
+ lll: queryLL,
162
+ llf: queryLL,
163
+ lln: queryO,
164
+ lfl: queryLF,
165
+ lff: queryLF,
166
+ lfn: (res, db, s, p, _, opts) => {
167
+ const sval = db[s];
168
+ sval != null && querySP(res, sval, s, p, null, opts);
169
+ },
170
+ lnl: queryLN,
171
+ lnf: queryLN,
172
+ lnn: (res, db, s) => {
173
+ const sval = db[s];
174
+ sval != null && collectFull(res, s, sval);
175
+ },
176
+ fll: queryFL,
177
+ flf: queryFL,
178
+ fln: (res, db, s, p, _, opts) => {
179
+ for (let $s in db) {
180
+ s($s) && queryO(res, db, $s, p, null, opts);
181
+ }
182
+ },
183
+ ffl: queryFF,
184
+ fff: queryFF,
185
+ ffn: (res, db, s, p, _, opts) => {
186
+ if (opts.partial) {
187
+ for (let $s in db) {
188
+ if (s($s)) {
189
+ const sval = db[$s];
190
+ for (let $p in sval) {
191
+ p($p) && addTriple(res, $s, $p, sval[$p]);
192
+ }
290
193
  }
291
- else {
292
- for (let s in db) {
293
- const sval = db[s];
294
- const val = sval[p];
295
- val != null && collectFull(res, s, sval);
194
+ }
195
+ } else {
196
+ for (let $s in db) {
197
+ if (s($s)) {
198
+ const sval = db[$s];
199
+ for (let $p in sval) {
200
+ if (p($p)) {
201
+ collectFull(res, $s, sval);
202
+ break;
296
203
  }
204
+ }
297
205
  }
298
- },
299
- nfl: queryNF,
300
- nff: queryNF,
301
- nfn: (res, db, _, p, __, opts) => {
302
- for (let s in db) {
303
- querySP(res, db[s], s, p, null, opts);
304
- }
305
- },
306
- nnl: queryNN,
307
- nnf: queryNN,
308
- nnn: (res, db) => Object.assign(res, db),
206
+ }
207
+ }
208
+ },
209
+ fnl: queryFN,
210
+ fnf: queryFN,
211
+ fnn: (res, db, s) => {
212
+ for (let $s in db) {
213
+ if (s($s)) {
214
+ const sval = db[$s];
215
+ sval != null && collectFull(res, $s, sval);
216
+ }
217
+ }
218
+ },
219
+ nll: queryNL,
220
+ nlf: queryNL,
221
+ nln: (res, db, _, p, __, opts) => {
222
+ if (opts.partial) {
223
+ for (let s in db) {
224
+ const val = db[s][p];
225
+ val != null && addTriple(res, s, p, val);
226
+ }
227
+ } else {
228
+ for (let s in db) {
229
+ const sval = db[s];
230
+ const val = sval[p];
231
+ val != null && collectFull(res, s, sval);
232
+ }
233
+ }
234
+ },
235
+ nfl: queryNF,
236
+ nff: queryNF,
237
+ nfn: (res, db, _, p, __, opts) => {
238
+ for (let s in db) {
239
+ querySP(res, db[s], s, p, null, opts);
240
+ }
241
+ },
242
+ nnl: queryNN,
243
+ nnf: queryNN,
244
+ nnn: (res, db) => Object.assign(res, db)
309
245
  };
310
- /**
311
- * Query function implementation, dispatches to one of the 27 optimized
312
- * functions based on given query pattern.
313
- *
314
- * @internal
315
- */
316
246
  const impl = defmulti((_, __, s, p, o) => classify(s) + classify(p) + classify(o), {}, IMPLS);
317
247
  const objQuery = (src, opts, args) => {
318
- const isIsec = opts.cwise && opts.intersect;
319
- isIsec && (opts.cwise = false);
320
- let [s, p, o, out] = args;
321
- out = out || {};
322
- impl(out, src, coerceStr(s), coerceStr(p), coerce(o, isIsec), opts);
323
- return out;
248
+ const isIsec = opts.cwise && opts.intersect;
249
+ isIsec && (opts.cwise = false);
250
+ let [s, p, o, out] = args;
251
+ out = out || {};
252
+ impl(
253
+ out,
254
+ src,
255
+ coerceStr(s),
256
+ coerceStr(p),
257
+ coerce(o, isIsec),
258
+ opts
259
+ );
260
+ return out;
324
261
  };
325
- const arrayQuery = (src, opts, p, o, collect) => {
326
- const isIsec = opts.cwise && opts.intersect;
327
- isIsec && (opts.cwise = false);
328
- const $p = coerceStr(p);
329
- const $o = coerce(o, isIsec);
330
- // pre-select implementation to avoid dynamic dispatch
331
- const impl = IMPLS[("n" + classify($p) + classify($o))];
332
- for (let i = 0, n = src.length; i < n; i++) {
333
- const res = {};
334
- impl(res, { _: src[i] }, "_", $p, $o, opts);
335
- res._ && collect(res._, i);
336
- }
262
+ const arrayQuery = (src, opts, p, o, collect2) => {
263
+ const isIsec = opts.cwise && opts.intersect;
264
+ isIsec && (opts.cwise = false);
265
+ const $p = coerceStr(p);
266
+ const $o = coerce(o, isIsec);
267
+ const impl2 = IMPLS["n" + classify($p) + classify($o)];
268
+ for (let i = 0, n = src.length; i < n; i++) {
269
+ const res = {};
270
+ impl2(res, { _: src[i] }, "_", $p, $o, opts);
271
+ res._ && collect2(res._, i);
272
+ }
337
273
  };
338
274
  const DEFAULT_OPTS = {
339
- partial: false,
340
- cwise: true,
341
- intersect: false,
342
- equiv,
275
+ partial: false,
276
+ cwise: true,
277
+ intersect: false,
278
+ equiv
343
279
  };
344
- /**
345
- * Generic Higher-order function to return an actual query function based on
346
- * given behavior options.
347
- *
348
- * @remarks
349
- * @see {@link QueryOpts}
350
- * @see {@link ObjQueryFn}
351
- * @see {@link ArrayQueryFn}
352
- * @see {@link defKeyQuery}
353
- *
354
- * @param opts -
355
- */
356
- export const defQuery = (opts) => {
357
- const $opts = { ...DEFAULT_OPTS, ...opts };
358
- return ((src, ...args) => {
359
- if (isArray(src)) {
360
- const out = args[2] || [];
361
- arrayQuery(src, $opts, args[0], args[1], (x) => out.push(x));
362
- return out;
363
- }
364
- else {
365
- return objQuery(src, $opts, args);
366
- }
367
- });
368
- };
369
- /**
370
- * Generic Higher-order function to return an actual query function based on
371
- * given behavior options. Unlike {@link defQuery}, key query functions only
372
- * return sets of keys (or indices) of matching objects.
373
- *
374
- * @remarks
375
- * @see {@link KeyQueryOpts}
376
- * @see {@link ObjKeyQueryFn}
377
- * @see {@link ArrayKeyQueryFn}
378
- *
379
- * @param opts -
380
- */
381
- export const defKeyQuery = (opts) => {
382
- const $opts = { ...DEFAULT_OPTS, ...opts };
383
- return ((src, ...args) => {
384
- if (isArray(src)) {
385
- const out = args[2] || new Set();
386
- arrayQuery(src, $opts, args[0], args[1], (_, i) => out.add(i));
387
- return out;
388
- }
389
- else {
390
- const res = objQuery(src, $opts, args.slice(0, 3));
391
- const out = args[3];
392
- if (!out)
393
- return new Set(Object.keys(res));
394
- for (let k in res)
395
- out.add(k);
396
- return out;
397
- }
398
- });
399
- };
400
- /**
401
- * Multi-term query function for collections (arrays) of {@link QueryObj}ects.
402
- * Takes a number of {@link QueryTerm}s and matches each term in succession
403
- * against the array of results of the previous terms (i.e. each sub-query is
404
- * potentially further narrowing the result set). Returns final results,
405
- * possibly post-processed, depending on given options.
406
- *
407
- * @remarks
408
- * Each {@link QueryTerm} can provide its own options and post-processing
409
- * function. Furthermore, global post-processing (e.g. limiting number of final
410
- * results, sorting by key) can be configured via `opts`.
411
- *
412
- * @param db
413
- * @param terms
414
- * @param opts
415
- */
416
- export const query = (db, terms, opts = {}) => {
417
- for (let term of terms) {
418
- if (!term)
419
- continue;
420
- db = (defQuery(term.opts)(db, term.q[0], term.q[1]));
421
- term.post && (db = term.post(db));
422
- if (!db.length)
423
- return db;
280
+ const defQuery = (opts) => {
281
+ const $opts = { ...DEFAULT_OPTS, ...opts };
282
+ return (src, ...args) => {
283
+ if (isArray(src)) {
284
+ const out = args[2] || [];
285
+ arrayQuery(src, $opts, args[0], args[1], (x) => out.push(x));
286
+ return out;
287
+ } else {
288
+ return objQuery(src, $opts, args);
424
289
  }
425
- const limit = opts.limit || 0;
426
- if (limit > 0 && limit < db.length) {
427
- db.length = limit;
428
- }
429
- if (opts.sort) {
430
- db.sort(compareByKey(opts.sort, opts.reverse ? reverse(compare) : compare));
290
+ };
291
+ };
292
+ const defKeyQuery = (opts) => {
293
+ const $opts = { ...DEFAULT_OPTS, ...opts };
294
+ return (src, ...args) => {
295
+ if (isArray(src)) {
296
+ const out = args[2] || /* @__PURE__ */ new Set();
297
+ arrayQuery(src, $opts, args[0], args[1], (_, i) => out.add(i));
298
+ return out;
299
+ } else {
300
+ const res = objQuery(src, $opts, args.slice(0, 3));
301
+ const out = args[3];
302
+ if (!out)
303
+ return new Set(Object.keys(res));
304
+ for (let k in res)
305
+ out.add(k);
306
+ return out;
431
307
  }
432
- return db;
308
+ };
309
+ };
310
+ const query = (db, terms, opts = {}) => {
311
+ for (let term of terms) {
312
+ if (!term)
313
+ continue;
314
+ db = defQuery(term.opts)(
315
+ db,
316
+ term.q[0],
317
+ term.q[1]
318
+ );
319
+ term.post && (db = term.post(db));
320
+ if (!db.length)
321
+ return db;
322
+ }
323
+ const limit = opts.limit || 0;
324
+ if (limit > 0 && limit < db.length) {
325
+ db.length = limit;
326
+ }
327
+ if (opts.sort) {
328
+ db.sort(
329
+ compareByKey(
330
+ opts.sort,
331
+ opts.reverse ? reverse(compare) : compare
332
+ )
333
+ );
334
+ }
335
+ return db;
336
+ };
337
+ export {
338
+ defKeyQuery,
339
+ defQuery,
340
+ query
433
341
  };