@snowtop/ent 0.1.0-alpha61 → 0.1.0-alpha68
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/core/base.d.ts +10 -2
- package/core/clause.d.ts +16 -0
- package/core/clause.js +87 -14
- package/core/ent.d.ts +28 -4
- package/core/ent.js +49 -3
- package/core/privacy.js +2 -5
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/package.json +1 -1
- package/schema/schema.d.ts +5 -0
- package/testutils/db/temp_db.js +1 -0
- package/testutils/parse_sql.d.ts +6 -0
- package/testutils/parse_sql.js +15 -5
package/core/base.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export interface QueryDataOptions {
|
|
|
72
72
|
orderby?: string;
|
|
73
73
|
groupby?: string;
|
|
74
74
|
limit?: number;
|
|
75
|
+
disableTransformations?: boolean;
|
|
75
76
|
}
|
|
76
77
|
export interface LoadRowOptions extends QueryableDataOptions {
|
|
77
78
|
}
|
|
@@ -85,13 +86,20 @@ export interface EditRowOptions extends CreateRowOptions {
|
|
|
85
86
|
whereClause: clause.Clause;
|
|
86
87
|
}
|
|
87
88
|
interface LoadableEntOptions<TEnt extends Ent, TViewer extends Viewer = Viewer> {
|
|
88
|
-
loaderFactory:
|
|
89
|
+
loaderFactory: LoaderFactoryWithOptions;
|
|
89
90
|
ent: EntConstructor<TEnt, TViewer>;
|
|
90
91
|
}
|
|
92
|
+
interface LoaderFactoryWithOptions extends LoaderFactory<any, Data | null> {
|
|
93
|
+
options?: SelectDataOptions;
|
|
94
|
+
}
|
|
91
95
|
export interface LoadEntOptions<TEnt extends Ent, TViewer extends Viewer = Viewer> extends LoadableEntOptions<TEnt, TViewer>, SelectBaseDataOptions {
|
|
92
96
|
fieldPrivacy?: Map<string, PrivacyPolicy>;
|
|
93
97
|
}
|
|
94
|
-
export interface
|
|
98
|
+
export interface SelectCustomDataOptions extends SelectBaseDataOptions {
|
|
99
|
+
clause?: clause.Clause;
|
|
100
|
+
loaderFactory?: LoaderFactoryWithOptions;
|
|
101
|
+
}
|
|
102
|
+
export interface LoadCustomEntOptions<TEnt extends Ent, TViewer extends Viewer = Viewer> extends SelectCustomDataOptions {
|
|
95
103
|
ent: EntConstructor<TEnt, TViewer>;
|
|
96
104
|
fieldPrivacy?: Map<string, PrivacyPolicy>;
|
|
97
105
|
}
|
package/core/clause.d.ts
CHANGED
|
@@ -56,6 +56,18 @@ export declare function PostgresArrayNotContainsValue(col: string, value: any):
|
|
|
56
56
|
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
57
57
|
*/
|
|
58
58
|
export declare function PostgresArrayNotContains(col: string, value: any[]): Clause;
|
|
59
|
+
/**
|
|
60
|
+
* creates a clause to determine if the arrays overlap, that is, do they have any elements in common
|
|
61
|
+
* only works with postgres gin indexes
|
|
62
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
63
|
+
*/
|
|
64
|
+
export declare function PostgresArrayOverlaps(col: string, value: any[]): Clause;
|
|
65
|
+
/**
|
|
66
|
+
* creates a clause to determine if the arrays do not overlap, that is, do they have any elements in common
|
|
67
|
+
* only works with postgres gin indexes
|
|
68
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
69
|
+
*/
|
|
70
|
+
export declare function PostgresArrayNotOverlaps(col: string, value: any[]): Clause;
|
|
59
71
|
/**
|
|
60
72
|
* @deprecated use PostgresArrayContainsValue
|
|
61
73
|
*/
|
|
@@ -87,4 +99,8 @@ export declare function TsVectorPlainToTsQuery(col: string, val: string | TsQuer
|
|
|
87
99
|
export declare function TsVectorPhraseToTsQuery(col: string, val: string | TsQuery): Clause;
|
|
88
100
|
export declare function TsVectorWebsearchToTsQuery(col: string, val: string | TsQuery): Clause;
|
|
89
101
|
export declare function sensitiveValue(val: any): SensitiveValue;
|
|
102
|
+
export declare function JSONObjectFieldKeyASJSON(col: string, field: string): string;
|
|
103
|
+
export declare function JSONObjectFieldKeyAsText(col: string, field: string): string;
|
|
104
|
+
declare type predicate = "==" | ">" | "<" | "!=" | ">=" | "<=";
|
|
105
|
+
export declare function JSONPathValuePredicate(dbCol: string, path: string, val: any, pred: predicate): Clause;
|
|
90
106
|
export {};
|
package/core/clause.js
CHANGED
|
@@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = void 0;
|
|
22
|
+
exports.JSONPathValuePredicate = exports.JSONObjectFieldKeyAsText = exports.JSONObjectFieldKeyASJSON = exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotOverlaps = exports.PostgresArrayOverlaps = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = void 0;
|
|
23
23
|
const db_1 = __importStar(require("./db"));
|
|
24
24
|
function isSensitive(val) {
|
|
25
25
|
return (val !== null &&
|
|
@@ -157,18 +157,19 @@ class arraySimpleClause {
|
|
|
157
157
|
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
class
|
|
161
|
-
constructor(col, value, not) {
|
|
160
|
+
class postgresArrayOperator {
|
|
161
|
+
constructor(col, value, op, not) {
|
|
162
162
|
this.col = col;
|
|
163
163
|
this.value = value;
|
|
164
|
+
this.op = op;
|
|
164
165
|
this.not = not;
|
|
165
166
|
}
|
|
166
167
|
clause(idx) {
|
|
167
168
|
if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
|
|
168
169
|
if (this.not) {
|
|
169
|
-
return `NOT ${this.col}
|
|
170
|
+
return `NOT ${this.col} ${this.op} $${idx}`;
|
|
170
171
|
}
|
|
171
|
-
return `${this.col}
|
|
172
|
+
return `${this.col} ${this.op} $${idx}`;
|
|
172
173
|
}
|
|
173
174
|
throw new Error(`not supported`);
|
|
174
175
|
}
|
|
@@ -189,14 +190,14 @@ class postgresArrayContains {
|
|
|
189
190
|
}
|
|
190
191
|
instanceKey() {
|
|
191
192
|
if (this.not) {
|
|
192
|
-
return `NOT:${this.col}
|
|
193
|
+
return `NOT:${this.col}${this.op}${rawValue(this.value)}`;
|
|
193
194
|
}
|
|
194
|
-
return `${this.col}
|
|
195
|
+
return `${this.col}${this.op}${rawValue(this.value)}`;
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
|
-
class
|
|
198
|
-
constructor(col, value, not) {
|
|
199
|
-
super(col, value, not);
|
|
198
|
+
class postgresArrayOperatorList extends postgresArrayOperator {
|
|
199
|
+
constructor(col, value, op, not) {
|
|
200
|
+
super(col, value, op, not);
|
|
200
201
|
}
|
|
201
202
|
values() {
|
|
202
203
|
return [
|
|
@@ -374,13 +375,15 @@ class websearchTosQueryClause extends tsQueryClause {
|
|
|
374
375
|
return "websearch_to_tsquery";
|
|
375
376
|
}
|
|
376
377
|
}
|
|
378
|
+
// postgres array operators
|
|
379
|
+
// https://www.postgresql.org/docs/current/functions-array.html
|
|
377
380
|
/**
|
|
378
381
|
* creates a clause to determine if the given value is contained in the array stored in the column in the db
|
|
379
382
|
* only works with postgres gin indexes
|
|
380
383
|
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
381
384
|
*/
|
|
382
385
|
function PostgresArrayContainsValue(col, value) {
|
|
383
|
-
return new
|
|
386
|
+
return new postgresArrayOperator(col, value, "@>");
|
|
384
387
|
}
|
|
385
388
|
exports.PostgresArrayContainsValue = PostgresArrayContainsValue;
|
|
386
389
|
/**
|
|
@@ -389,7 +392,7 @@ exports.PostgresArrayContainsValue = PostgresArrayContainsValue;
|
|
|
389
392
|
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
390
393
|
*/
|
|
391
394
|
function PostgresArrayContains(col, value) {
|
|
392
|
-
return new
|
|
395
|
+
return new postgresArrayOperatorList(col, value, "@>");
|
|
393
396
|
}
|
|
394
397
|
exports.PostgresArrayContains = PostgresArrayContains;
|
|
395
398
|
/**
|
|
@@ -398,7 +401,7 @@ exports.PostgresArrayContains = PostgresArrayContains;
|
|
|
398
401
|
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
399
402
|
*/
|
|
400
403
|
function PostgresArrayNotContainsValue(col, value) {
|
|
401
|
-
return new
|
|
404
|
+
return new postgresArrayOperator(col, value, "@>", true);
|
|
402
405
|
}
|
|
403
406
|
exports.PostgresArrayNotContainsValue = PostgresArrayNotContainsValue;
|
|
404
407
|
/**
|
|
@@ -407,9 +410,27 @@ exports.PostgresArrayNotContainsValue = PostgresArrayNotContainsValue;
|
|
|
407
410
|
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
408
411
|
*/
|
|
409
412
|
function PostgresArrayNotContains(col, value) {
|
|
410
|
-
return new
|
|
413
|
+
return new postgresArrayOperatorList(col, value, "@>", true);
|
|
411
414
|
}
|
|
412
415
|
exports.PostgresArrayNotContains = PostgresArrayNotContains;
|
|
416
|
+
/**
|
|
417
|
+
* creates a clause to determine if the arrays overlap, that is, do they have any elements in common
|
|
418
|
+
* only works with postgres gin indexes
|
|
419
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
420
|
+
*/
|
|
421
|
+
function PostgresArrayOverlaps(col, value) {
|
|
422
|
+
return new postgresArrayOperatorList(col, value, "&&");
|
|
423
|
+
}
|
|
424
|
+
exports.PostgresArrayOverlaps = PostgresArrayOverlaps;
|
|
425
|
+
/**
|
|
426
|
+
* creates a clause to determine if the arrays do not overlap, that is, do they have any elements in common
|
|
427
|
+
* only works with postgres gin indexes
|
|
428
|
+
* https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
|
|
429
|
+
*/
|
|
430
|
+
function PostgresArrayNotOverlaps(col, value) {
|
|
431
|
+
return new postgresArrayOperatorList(col, value, "&&", true);
|
|
432
|
+
}
|
|
433
|
+
exports.PostgresArrayNotOverlaps = PostgresArrayNotOverlaps;
|
|
413
434
|
/**
|
|
414
435
|
* @deprecated use PostgresArrayContainsValue
|
|
415
436
|
*/
|
|
@@ -538,3 +559,55 @@ function sensitiveValue(val) {
|
|
|
538
559
|
};
|
|
539
560
|
}
|
|
540
561
|
exports.sensitiveValue = sensitiveValue;
|
|
562
|
+
// These don't return Clauses but return helpful things that can be passed to clauses
|
|
563
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
564
|
+
// see test in db_clause.test.ts
|
|
565
|
+
// unclear best time to use this...
|
|
566
|
+
function JSONObjectFieldKeyASJSON(col, field) {
|
|
567
|
+
return `${col}->'${field}'`;
|
|
568
|
+
}
|
|
569
|
+
exports.JSONObjectFieldKeyASJSON = JSONObjectFieldKeyASJSON;
|
|
570
|
+
function JSONObjectFieldKeyAsText(col, field) {
|
|
571
|
+
return `${col}->>'${field}'`;
|
|
572
|
+
}
|
|
573
|
+
exports.JSONObjectFieldKeyAsText = JSONObjectFieldKeyAsText;
|
|
574
|
+
class jSONPathValuePredicateClause {
|
|
575
|
+
constructor(col, path, value, pred) {
|
|
576
|
+
this.col = col;
|
|
577
|
+
this.path = path;
|
|
578
|
+
this.value = value;
|
|
579
|
+
this.pred = pred;
|
|
580
|
+
}
|
|
581
|
+
clause(idx) {
|
|
582
|
+
if (db_1.default.getDialect() !== db_1.Dialect.Postgres) {
|
|
583
|
+
throw new Error(`not supported`);
|
|
584
|
+
}
|
|
585
|
+
return `${this.col} @@ $${idx}`;
|
|
586
|
+
}
|
|
587
|
+
columns() {
|
|
588
|
+
return [this.col];
|
|
589
|
+
}
|
|
590
|
+
wrap(val) {
|
|
591
|
+
return `${this.path} ${this.pred} ${JSON.stringify(val)}`;
|
|
592
|
+
}
|
|
593
|
+
values() {
|
|
594
|
+
if (isSensitive(this.value)) {
|
|
595
|
+
return [this.wrap(this.value.value())];
|
|
596
|
+
}
|
|
597
|
+
return [this.wrap(this.value)];
|
|
598
|
+
}
|
|
599
|
+
logValues() {
|
|
600
|
+
if (isSensitive(this.value)) {
|
|
601
|
+
return [this.wrap(this.value.logValue())];
|
|
602
|
+
}
|
|
603
|
+
return [this.wrap(this.value)];
|
|
604
|
+
}
|
|
605
|
+
instanceKey() {
|
|
606
|
+
return `${this.col}${this.path}${rawValue(this.value)}${this.pred}`;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// https://www.postgresql.org/docs/12/functions-json.html#FUNCTIONS-JSON-OP-TABLE
|
|
610
|
+
function JSONPathValuePredicate(dbCol, path, val, pred) {
|
|
611
|
+
return new jSONPathValuePredicateClause(dbCol, path, val, pred);
|
|
612
|
+
}
|
|
613
|
+
exports.JSONPathValuePredicate = JSONPathValuePredicate;
|
package/core/ent.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Queryer, SyncQueryer } from "./db";
|
|
2
|
-
import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context,
|
|
2
|
+
import { Viewer, Ent, ID, LoadRowsOptions, LoadRowOptions, Data, DataOptions, QueryableDataOptions, EditRowOptions, LoadEntOptions, LoadCustomEntOptions, EdgeQueryableDataOptions, Context, CreateRowOptions, QueryDataOptions, SelectCustomDataOptions } from "./base";
|
|
3
3
|
import { Executor } from "../action/action";
|
|
4
4
|
import * as clause from "./clause";
|
|
5
5
|
import { Builder } from "../action";
|
|
@@ -15,13 +15,37 @@ export declare function loadEnts<TEnt extends Ent<TViewer>, TViewer extends View
|
|
|
15
15
|
export declare function loadEntsList<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, options: LoadEntOptions<TEnt, TViewer>, ...ids: ID[]): Promise<TEnt[]>;
|
|
16
16
|
export declare function loadEntsFromClause<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, clause: clause.Clause, options: LoadEntOptions<TEnt, TViewer>): Promise<Map<ID, TEnt>>;
|
|
17
17
|
export declare function loadCustomEnts<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, options: LoadCustomEntOptions<TEnt, TViewer>, query: CustomQuery): Promise<TEnt[]>;
|
|
18
|
-
interface
|
|
18
|
+
interface parameterizedQueryOptions {
|
|
19
19
|
query: string;
|
|
20
20
|
values?: any[];
|
|
21
21
|
logValues?: any[];
|
|
22
22
|
}
|
|
23
|
-
export declare type CustomQuery = string |
|
|
24
|
-
|
|
23
|
+
export declare type CustomQuery = string | parameterizedQueryOptions | clause.Clause | QueryDataOptions;
|
|
24
|
+
/**
|
|
25
|
+
* Note that if there's default read transformations (e.g. soft delete) and a clause is passed in
|
|
26
|
+
* either as Clause or QueryDataOptions without {disableTransformations: true}, the default transformation
|
|
27
|
+
* (e.g. soft delete) is applied.
|
|
28
|
+
*
|
|
29
|
+
* Passing a full SQL string or Paramterized SQL string doesn't apply it and the given string is sent to the
|
|
30
|
+
* database as written.
|
|
31
|
+
*
|
|
32
|
+
* e.g.
|
|
33
|
+
* Foo.loadCustom(opts, 'SELECT * FROM foo') // doesn't change the query
|
|
34
|
+
* Foo.loadCustom(opts, { query: 'SELECT * FROM foo WHERE id = ?', values: [1]}) // doesn't change the query
|
|
35
|
+
* Foo.loadCustom(opts, query.Eq('time', Date.now())) // changes the query
|
|
36
|
+
* Foo.loadCustom(opts, {
|
|
37
|
+
* clause: query.LessEq('time', Date.now()),
|
|
38
|
+
* limit: 100,
|
|
39
|
+
* orderby: 'time',
|
|
40
|
+
* }) // changes the query
|
|
41
|
+
* Foo.loadCustom(opts, {
|
|
42
|
+
* clause: query.LessEq('time', Date.now()),
|
|
43
|
+
* limit: 100,
|
|
44
|
+
* orderby: 'time',
|
|
45
|
+
* disableTransformations: false
|
|
46
|
+
* }) // doesn't change the query
|
|
47
|
+
*/
|
|
48
|
+
export declare function loadCustomData(options: SelectCustomDataOptions, query: CustomQuery, context: Context | undefined): Promise<Data[]>;
|
|
25
49
|
export declare function loadDerivedEnt<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, data: Data, loader: new (viewer: TViewer, data: Data) => TEnt): Promise<TEnt | null>;
|
|
26
50
|
export declare function loadDerivedEntX<TEnt extends Ent<TViewer>, TViewer extends Viewer>(viewer: TViewer, data: Data, loader: new (viewer: TViewer, data: Data) => TEnt): Promise<TEnt>;
|
|
27
51
|
export declare function loadRowX(options: LoadRowOptions): Promise<Data>;
|
package/core/ent.js
CHANGED
|
@@ -226,32 +226,78 @@ function isClause(opts) {
|
|
|
226
226
|
const cls = opts;
|
|
227
227
|
return cls.clause !== undefined && cls.values !== undefined;
|
|
228
228
|
}
|
|
229
|
-
function
|
|
229
|
+
function isParameterizedQuery(opts) {
|
|
230
230
|
return opts.query !== undefined;
|
|
231
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Note that if there's default read transformations (e.g. soft delete) and a clause is passed in
|
|
234
|
+
* either as Clause or QueryDataOptions without {disableTransformations: true}, the default transformation
|
|
235
|
+
* (e.g. soft delete) is applied.
|
|
236
|
+
*
|
|
237
|
+
* Passing a full SQL string or Paramterized SQL string doesn't apply it and the given string is sent to the
|
|
238
|
+
* database as written.
|
|
239
|
+
*
|
|
240
|
+
* e.g.
|
|
241
|
+
* Foo.loadCustom(opts, 'SELECT * FROM foo') // doesn't change the query
|
|
242
|
+
* Foo.loadCustom(opts, { query: 'SELECT * FROM foo WHERE id = ?', values: [1]}) // doesn't change the query
|
|
243
|
+
* Foo.loadCustom(opts, query.Eq('time', Date.now())) // changes the query
|
|
244
|
+
* Foo.loadCustom(opts, {
|
|
245
|
+
* clause: query.LessEq('time', Date.now()),
|
|
246
|
+
* limit: 100,
|
|
247
|
+
* orderby: 'time',
|
|
248
|
+
* }) // changes the query
|
|
249
|
+
* Foo.loadCustom(opts, {
|
|
250
|
+
* clause: query.LessEq('time', Date.now()),
|
|
251
|
+
* limit: 100,
|
|
252
|
+
* orderby: 'time',
|
|
253
|
+
* disableTransformations: false
|
|
254
|
+
* }) // doesn't change the query
|
|
255
|
+
*/
|
|
232
256
|
async function loadCustomData(options, query, context) {
|
|
257
|
+
function getClause(cls) {
|
|
258
|
+
if (options.clause && options.loaderFactory?.options?.clause) {
|
|
259
|
+
throw new Error(`cannot pass both options.clause && optsions.loaderFactory.options.clause`);
|
|
260
|
+
}
|
|
261
|
+
let optClause = options.clause || options.loaderFactory?.options?.clause;
|
|
262
|
+
if (typeof optClause === "function") {
|
|
263
|
+
optClause = optClause();
|
|
264
|
+
}
|
|
265
|
+
if (!optClause) {
|
|
266
|
+
return cls;
|
|
267
|
+
}
|
|
268
|
+
return clause.And(cls, optClause);
|
|
269
|
+
}
|
|
233
270
|
if (typeof query === "string") {
|
|
234
271
|
// no caching, perform raw query
|
|
235
272
|
return await performRawQuery(query, [], []);
|
|
236
273
|
}
|
|
237
274
|
else if (isClause(query)) {
|
|
275
|
+
// if a Clause is passed in and we have a default clause
|
|
276
|
+
// associated with the query, pass that in
|
|
277
|
+
// if we want to disableTransformations, need to indicate that with
|
|
278
|
+
// disableTransformations option
|
|
238
279
|
// this will have rudimentary caching but nothing crazy
|
|
239
280
|
return await loadRows({
|
|
240
281
|
...options,
|
|
241
|
-
clause: query,
|
|
282
|
+
clause: getClause(query),
|
|
242
283
|
context: context,
|
|
243
284
|
});
|
|
244
285
|
}
|
|
245
|
-
else if (
|
|
286
|
+
else if (isParameterizedQuery(query)) {
|
|
246
287
|
// no caching, perform raw query
|
|
247
288
|
return await performRawQuery(query.query, query.values || [], query.logValues);
|
|
248
289
|
}
|
|
249
290
|
else {
|
|
291
|
+
let cls = query.clause;
|
|
292
|
+
if (!query.disableTransformations) {
|
|
293
|
+
cls = getClause(cls);
|
|
294
|
+
}
|
|
250
295
|
// this will have rudimentary caching but nothing crazy
|
|
251
296
|
return await loadRows({
|
|
252
297
|
...query,
|
|
253
298
|
...options,
|
|
254
299
|
context: context,
|
|
300
|
+
clause: cls,
|
|
255
301
|
});
|
|
256
302
|
}
|
|
257
303
|
}
|
package/core/privacy.js
CHANGED
|
@@ -451,11 +451,8 @@ async function applyPrivacyPolicy(v, policy, ent) {
|
|
|
451
451
|
exports.applyPrivacyPolicy = applyPrivacyPolicy;
|
|
452
452
|
// this will throw an exception if fails or return error | null?
|
|
453
453
|
async function applyPrivacyPolicyX(v, policy, ent, throwErr) {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
for (let i = 0; i < results.length; i++) {
|
|
457
|
-
const res = results[i];
|
|
458
|
-
const rule = policy.rules[i];
|
|
454
|
+
for (const rule of policy.rules) {
|
|
455
|
+
const res = await rule.apply(v, ent);
|
|
459
456
|
if (res.result == privacyResult.Allow) {
|
|
460
457
|
return true;
|
|
461
458
|
}
|
package/index.d.ts
CHANGED
|
@@ -24,6 +24,11 @@ declare const query: {
|
|
|
24
24
|
PostgresArrayContains: typeof q.PostgresArrayContains;
|
|
25
25
|
PostgresArrayNotContainsValue: typeof q.PostgresArrayNotContainsValue;
|
|
26
26
|
PostgresArrayNotContains: typeof q.PostgresArrayNotContains;
|
|
27
|
+
PostgresArrayOverlaps: typeof q.PostgresArrayOverlaps;
|
|
28
|
+
PostgresArrayNotOverlaps: typeof q.PostgresArrayNotOverlaps;
|
|
29
|
+
JSONPathValuePredicate: typeof q.JSONPathValuePredicate;
|
|
30
|
+
JSONObjectFieldKeyASJSON: typeof q.JSONObjectFieldKeyASJSON;
|
|
31
|
+
JSONObjectFieldKeyAsText: typeof q.JSONObjectFieldKeyAsText;
|
|
27
32
|
TsQuery: typeof q.TsQuery;
|
|
28
33
|
PlainToTsQuery: typeof q.PlainToTsQuery;
|
|
29
34
|
PhraseToTsQuery: typeof q.PhraseToTsQuery;
|
package/index.js
CHANGED
|
@@ -121,6 +121,11 @@ const query = {
|
|
|
121
121
|
PostgresArrayContains: q.PostgresArrayContains,
|
|
122
122
|
PostgresArrayNotContainsValue: q.PostgresArrayNotContainsValue,
|
|
123
123
|
PostgresArrayNotContains: q.PostgresArrayNotContains,
|
|
124
|
+
PostgresArrayOverlaps: q.PostgresArrayOverlaps,
|
|
125
|
+
PostgresArrayNotOverlaps: q.PostgresArrayNotOverlaps,
|
|
126
|
+
JSONPathValuePredicate: q.JSONPathValuePredicate,
|
|
127
|
+
JSONObjectFieldKeyASJSON: q.JSONObjectFieldKeyASJSON,
|
|
128
|
+
JSONObjectFieldKeyAsText: q.JSONObjectFieldKeyAsText,
|
|
124
129
|
TsQuery: q.TsQuery,
|
|
125
130
|
PlainToTsQuery: q.PlainToTsQuery,
|
|
126
131
|
PhraseToTsQuery: q.PhraseToTsQuery,
|
package/package.json
CHANGED
package/schema/schema.d.ts
CHANGED
|
@@ -133,6 +133,10 @@ export interface ImportType {
|
|
|
133
133
|
type: string;
|
|
134
134
|
[x: string]: any;
|
|
135
135
|
}
|
|
136
|
+
export interface ConvertType {
|
|
137
|
+
path: string;
|
|
138
|
+
function: string;
|
|
139
|
+
}
|
|
136
140
|
declare type EnumMap = {
|
|
137
141
|
[key: string]: string;
|
|
138
142
|
};
|
|
@@ -200,6 +204,7 @@ export interface FieldOptions {
|
|
|
200
204
|
polymorphic?: boolean | PolymorphicOptions;
|
|
201
205
|
privacyPolicy?: PrivacyPolicy | (() => PrivacyPolicy);
|
|
202
206
|
getDerivedFields?(name: string): FieldMap;
|
|
207
|
+
convert?: ConvertType;
|
|
203
208
|
[x: string]: any;
|
|
204
209
|
}
|
|
205
210
|
export interface PolymorphicOptions {
|
package/testutils/db/temp_db.js
CHANGED
package/testutils/parse_sql.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export declare class EqOp {
|
|
|
9
9
|
constructor(col: string, value: any);
|
|
10
10
|
apply(data: Data): boolean;
|
|
11
11
|
}
|
|
12
|
+
export declare class NotEqOp {
|
|
13
|
+
private col;
|
|
14
|
+
private value;
|
|
15
|
+
constructor(col: string, value: any);
|
|
16
|
+
apply(data: Data): boolean;
|
|
17
|
+
}
|
|
12
18
|
export declare class GreaterOp {
|
|
13
19
|
private col;
|
|
14
20
|
private value;
|
package/testutils/parse_sql.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.performQuery = exports.OrOp = exports.AndOp = exports.InOp = exports.LessEqOp = exports.GreaterEqOp = exports.LessOp = exports.GreaterOp = exports.EqOp = exports.getDataToReturn = void 0;
|
|
3
|
+
exports.performQuery = exports.OrOp = exports.AndOp = exports.InOp = exports.LessEqOp = exports.GreaterEqOp = exports.LessOp = exports.GreaterOp = exports.NotEqOp = exports.EqOp = exports.getDataToReturn = void 0;
|
|
4
4
|
const node_sql_parser_1 = require("node-sql-parser");
|
|
5
5
|
function getTableName(table) {
|
|
6
6
|
if (Array.isArray(table)) {
|
|
@@ -184,6 +184,16 @@ class EqOp {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
exports.EqOp = EqOp;
|
|
187
|
+
class NotEqOp {
|
|
188
|
+
constructor(col, value) {
|
|
189
|
+
this.col = col;
|
|
190
|
+
this.value = value;
|
|
191
|
+
}
|
|
192
|
+
apply(data) {
|
|
193
|
+
return data[this.col] !== this.value;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.NotEqOp = NotEqOp;
|
|
187
197
|
class GreaterOp {
|
|
188
198
|
constructor(col, value) {
|
|
189
199
|
this.col = col;
|
|
@@ -308,11 +318,11 @@ function getOp(where, values) {
|
|
|
308
318
|
case "OR":
|
|
309
319
|
return new OrOp([getOp(where.left, values), getOp(where.right, values)]);
|
|
310
320
|
case "IS":
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
321
|
+
return new EqOp(getColumnFromRef(where.left), where.right?.value);
|
|
322
|
+
case "IS NOT":
|
|
323
|
+
return new NotEqOp(getColumnFromRef(where.left), where.right?.value);
|
|
314
324
|
default:
|
|
315
|
-
console.
|
|
325
|
+
console.debug(where);
|
|
316
326
|
throw new Error(`unsupported op ${where.operator}`);
|
|
317
327
|
}
|
|
318
328
|
}
|