@snowtop/ent 0.1.0-alpha16 → 0.1.0-alpha160-test2
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/action/action.d.ts +25 -14
- package/action/action.js +22 -7
- package/action/executor.d.ts +16 -3
- package/action/executor.js +89 -28
- package/action/experimental_action.d.ts +25 -16
- package/action/experimental_action.js +34 -14
- package/action/index.d.ts +4 -1
- package/action/index.js +7 -1
- package/action/operations.d.ts +126 -0
- package/action/operations.js +686 -0
- package/action/orchestrator.d.ts +43 -12
- package/action/orchestrator.js +461 -101
- package/action/relative_value.d.ts +47 -0
- package/action/relative_value.js +125 -0
- package/action/transaction.d.ts +10 -0
- package/action/transaction.js +23 -0
- package/auth/auth.d.ts +1 -1
- package/core/base.d.ts +56 -23
- package/core/base.js +7 -1
- package/core/clause.d.ts +103 -39
- package/core/clause.js +430 -66
- package/core/config.d.ts +13 -3
- package/core/config.js +10 -1
- package/core/const.d.ts +3 -0
- package/core/const.js +6 -0
- package/core/context.d.ts +6 -3
- package/core/context.js +22 -3
- package/core/convert.d.ts +1 -1
- package/core/date.js +1 -5
- package/core/db.d.ts +12 -8
- package/core/db.js +21 -9
- package/core/ent.d.ts +99 -95
- package/core/ent.js +550 -602
- package/core/global_schema.d.ts +7 -0
- package/core/global_schema.js +51 -0
- package/core/loaders/assoc_count_loader.d.ts +5 -2
- package/core/loaders/assoc_count_loader.js +19 -3
- package/core/loaders/assoc_edge_loader.d.ts +2 -3
- package/core/loaders/assoc_edge_loader.js +23 -17
- package/core/loaders/index.d.ts +1 -2
- package/core/loaders/index.js +1 -5
- package/core/loaders/loader.d.ts +3 -3
- package/core/loaders/loader.js +4 -21
- package/core/loaders/object_loader.d.ts +30 -9
- package/core/loaders/object_loader.js +226 -79
- package/core/loaders/query_loader.d.ts +7 -13
- package/core/loaders/query_loader.js +60 -24
- package/core/loaders/raw_count_loader.d.ts +1 -0
- package/core/loaders/raw_count_loader.js +8 -3
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +26 -16
- package/core/privacy.js +68 -51
- package/core/query/assoc_query.d.ts +3 -2
- package/core/query/assoc_query.js +10 -2
- package/core/query/custom_clause_query.d.ts +29 -0
- package/core/query/custom_clause_query.js +105 -0
- package/core/query/custom_query.d.ts +19 -2
- package/core/query/custom_query.js +111 -13
- package/core/query/index.d.ts +1 -0
- package/core/query/index.js +3 -1
- package/core/query/query.d.ts +18 -4
- package/core/query/query.js +135 -58
- package/core/query/shared_assoc_test.d.ts +2 -1
- package/core/query/shared_assoc_test.js +186 -55
- package/core/query/shared_test.d.ts +9 -2
- package/core/query/shared_test.js +529 -236
- package/core/query_impl.d.ts +8 -0
- package/core/query_impl.js +28 -0
- package/core/viewer.d.ts +2 -0
- package/core/viewer.js +3 -1
- package/graphql/graphql.d.ts +108 -22
- package/graphql/graphql.js +183 -137
- package/graphql/graphql_field_helpers.d.ts +9 -3
- package/graphql/graphql_field_helpers.js +22 -2
- package/graphql/index.d.ts +2 -2
- package/graphql/index.js +5 -5
- package/graphql/query/connection_type.d.ts +9 -9
- package/graphql/query/shared_assoc_test.js +1 -1
- package/graphql/query/shared_edge_connection.js +1 -19
- package/graphql/scalars/orderby_direction.d.ts +2 -0
- package/graphql/scalars/orderby_direction.js +15 -0
- package/imports/dataz/example1/_auth.js +128 -47
- package/imports/dataz/example1/_viewer.js +87 -39
- package/imports/index.d.ts +7 -2
- package/imports/index.js +20 -5
- package/index.d.ts +23 -5
- package/index.js +35 -10
- package/package.json +20 -19
- package/parse_schema/parse.d.ts +33 -9
- package/parse_schema/parse.js +182 -33
- package/schema/base_schema.d.ts +13 -3
- package/schema/base_schema.js +13 -0
- package/schema/field.d.ts +78 -21
- package/schema/field.js +232 -72
- package/schema/index.d.ts +2 -2
- package/schema/index.js +7 -2
- package/schema/json_field.d.ts +16 -4
- package/schema/json_field.js +32 -2
- package/schema/schema.d.ts +109 -20
- package/schema/schema.js +42 -53
- package/schema/struct_field.d.ts +15 -3
- package/schema/struct_field.js +117 -22
- package/schema/union_field.d.ts +1 -1
- package/scripts/custom_compiler.js +12 -8
- package/scripts/custom_graphql.js +167 -64
- package/scripts/migrate_v0.1.js +36 -0
- package/scripts/move_types.js +120 -0
- package/scripts/read_schema.js +22 -7
- package/testutils/action/complex_schemas.d.ts +69 -0
- package/testutils/action/complex_schemas.js +405 -0
- package/testutils/builder.d.ts +37 -41
- package/testutils/builder.js +66 -46
- package/testutils/db/fixture.d.ts +10 -0
- package/testutils/db/fixture.js +26 -0
- package/testutils/db/{test_db.d.ts → temp_db.d.ts} +32 -8
- package/testutils/db/{test_db.js → temp_db.js} +251 -48
- package/testutils/db/value.d.ts +7 -0
- package/testutils/db/value.js +251 -0
- package/testutils/db_mock.d.ts +16 -4
- package/testutils/db_mock.js +52 -9
- package/testutils/db_time_zone.d.ts +4 -0
- package/testutils/db_time_zone.js +41 -0
- package/testutils/ent-graphql-tests/index.d.ts +7 -1
- package/testutils/ent-graphql-tests/index.js +56 -26
- package/testutils/fake_comms.js +1 -1
- package/testutils/fake_data/const.d.ts +2 -1
- package/testutils/fake_data/const.js +3 -0
- package/testutils/fake_data/fake_contact.d.ts +7 -3
- package/testutils/fake_data/fake_contact.js +13 -7
- package/testutils/fake_data/fake_event.d.ts +4 -1
- package/testutils/fake_data/fake_event.js +7 -6
- package/testutils/fake_data/fake_tag.d.ts +36 -0
- package/testutils/fake_data/fake_tag.js +89 -0
- package/testutils/fake_data/fake_user.d.ts +8 -5
- package/testutils/fake_data/fake_user.js +31 -19
- package/testutils/fake_data/index.js +5 -1
- package/testutils/fake_data/internal.d.ts +2 -0
- package/testutils/fake_data/internal.js +7 -1
- package/testutils/fake_data/tag_query.d.ts +13 -0
- package/testutils/fake_data/tag_query.js +48 -0
- package/testutils/fake_data/test_helpers.d.ts +14 -6
- package/testutils/fake_data/test_helpers.js +31 -15
- package/testutils/fake_data/user_query.d.ts +16 -6
- package/testutils/fake_data/user_query.js +72 -23
- package/testutils/fake_log.js +1 -1
- package/testutils/parse_sql.d.ts +6 -0
- package/testutils/parse_sql.js +16 -2
- package/testutils/test_edge_global_schema.d.ts +15 -0
- package/testutils/test_edge_global_schema.js +62 -0
- package/testutils/write.d.ts +2 -2
- package/testutils/write.js +33 -7
- package/tsc/ast.d.ts +15 -3
- package/tsc/ast.js +114 -23
- package/tsc/compilerOptions.js +5 -1
- package/tsc/move_generated.d.ts +1 -0
- package/tsc/move_generated.js +164 -0
- package/tsc/transform.d.ts +22 -0
- package/tsc/transform.js +182 -0
- package/tsc/transform_action.d.ts +22 -0
- package/tsc/transform_action.js +183 -0
- package/tsc/transform_ent.d.ts +17 -0
- package/tsc/transform_ent.js +60 -0
- package/tsc/transform_schema.d.ts +27 -0
- package/{scripts → tsc}/transform_schema.js +146 -117
- package/core/loaders/index_loader.d.ts +0 -14
- package/core/loaders/index_loader.js +0 -27
- package/graphql/enums.d.ts +0 -3
- package/graphql/enums.js +0 -25
- package/scripts/move_generated.js +0 -141
- package/scripts/transform_actions.js +0 -266
- package/scripts/transform_code.d.ts +0 -1
- package/scripts/transform_code.js +0 -111
- package/scripts/transform_schema.d.ts +0 -1
- /package/scripts/{move_generated.d.ts → migrate_v0.1.d.ts} +0 -0
- /package/scripts/{transform_actions.d.ts → move_types.d.ts} +0 -0
|
@@ -1,20 +1,104 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CustomEdgeQueryBase = void 0;
|
|
4
|
+
const clause_1 = require("../clause");
|
|
4
5
|
const ent_1 = require("../ent");
|
|
6
|
+
const loaders_1 = require("../loaders");
|
|
5
7
|
const query_1 = require("./query");
|
|
8
|
+
function getClause(opts) {
|
|
9
|
+
let cls = opts.clause;
|
|
10
|
+
if (opts.disableTransformations) {
|
|
11
|
+
return cls;
|
|
12
|
+
}
|
|
13
|
+
let optClause = opts.loadEntOptions.loaderFactory?.options?.clause;
|
|
14
|
+
if (typeof optClause === "function") {
|
|
15
|
+
optClause = optClause();
|
|
16
|
+
}
|
|
17
|
+
if (!optClause) {
|
|
18
|
+
return cls;
|
|
19
|
+
}
|
|
20
|
+
return (0, clause_1.AndOptional)(cls, optClause);
|
|
21
|
+
}
|
|
22
|
+
function getRawCountLoader(viewer, opts) {
|
|
23
|
+
if (!viewer.context?.cache) {
|
|
24
|
+
return new loaders_1.RawCountLoader({
|
|
25
|
+
tableName: opts.loadEntOptions.tableName,
|
|
26
|
+
groupCol: opts.groupCol,
|
|
27
|
+
clause: getClause(opts),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const name = `custom_query_count_loader:${opts.name}`;
|
|
31
|
+
return viewer.context.cache.getLoader(name, () => new loaders_1.RawCountLoader({
|
|
32
|
+
tableName: opts.loadEntOptions.tableName,
|
|
33
|
+
groupCol: opts.groupCol,
|
|
34
|
+
clause: getClause(opts),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function getQueryLoader(viewer, opts, options) {
|
|
38
|
+
const loader = opts.loadEntOptions.loaderFactory;
|
|
39
|
+
const name = `custom_query_loader:${opts.name}`;
|
|
40
|
+
return loaders_1.QueryLoaderFactory.createConfigurableLoader(name, {
|
|
41
|
+
tableName: opts.loadEntOptions.tableName,
|
|
42
|
+
fields: opts.loadEntOptions.fields,
|
|
43
|
+
groupCol: opts.groupCol,
|
|
44
|
+
clause: getClause(opts),
|
|
45
|
+
toPrime: [loader],
|
|
46
|
+
}, options, viewer.context);
|
|
47
|
+
}
|
|
48
|
+
function isDeprecatedOptions(options) {
|
|
49
|
+
return (options
|
|
50
|
+
.countLoaderFactory !== undefined);
|
|
51
|
+
}
|
|
6
52
|
class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
|
|
7
53
|
constructor(viewer, options) {
|
|
8
|
-
|
|
54
|
+
let opts;
|
|
55
|
+
let defaultSort = "id";
|
|
56
|
+
let uniqueColIsSort = false;
|
|
57
|
+
let orderby;
|
|
58
|
+
let sortCol;
|
|
59
|
+
if (isDeprecatedOptions(options)) {
|
|
60
|
+
opts = options.options;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
opts = options.loadEntOptions;
|
|
64
|
+
if (options.primarySortColIsUnique) {
|
|
65
|
+
uniqueColIsSort = true;
|
|
66
|
+
}
|
|
67
|
+
if (options.orderby) {
|
|
68
|
+
orderby = options.orderby;
|
|
69
|
+
sortCol = options.orderby[0].column;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let uniqueCol = opts.loaderFactory.options?.key || "id";
|
|
73
|
+
if (!orderby) {
|
|
74
|
+
options.sortColumn = options.sortColumn || defaultSort;
|
|
75
|
+
sortCol = options.sortColumn;
|
|
76
|
+
orderby = [
|
|
77
|
+
{
|
|
78
|
+
column: options.sortColumn,
|
|
79
|
+
direction: "DESC",
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
if (uniqueColIsSort) {
|
|
84
|
+
uniqueCol = sortCol || defaultSort;
|
|
85
|
+
}
|
|
86
|
+
super(viewer, {
|
|
87
|
+
cursorCol: uniqueCol,
|
|
88
|
+
orderby,
|
|
89
|
+
});
|
|
9
90
|
this.viewer = viewer;
|
|
10
91
|
this.options = options;
|
|
11
|
-
options.sortColumn = options.sortColumn || "created_at";
|
|
12
92
|
if (typeof options.src === "object") {
|
|
13
93
|
this.id = options.src.id;
|
|
14
94
|
}
|
|
15
95
|
else {
|
|
16
96
|
this.id = options.src;
|
|
17
97
|
}
|
|
98
|
+
this.opts = opts;
|
|
99
|
+
}
|
|
100
|
+
getTableName() {
|
|
101
|
+
return this.opts.tableName;
|
|
18
102
|
}
|
|
19
103
|
async idVisible() {
|
|
20
104
|
const ids = await this.genIDInfosToFetch();
|
|
@@ -23,14 +107,24 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
|
|
|
23
107
|
}
|
|
24
108
|
return !ids[0].invalidated;
|
|
25
109
|
}
|
|
110
|
+
getCountLoader() {
|
|
111
|
+
if (isDeprecatedOptions(this.options)) {
|
|
112
|
+
return this.options.countLoaderFactory.createLoader(this.viewer.context);
|
|
113
|
+
}
|
|
114
|
+
return getRawCountLoader(this.viewer, this.options);
|
|
115
|
+
}
|
|
116
|
+
getQueryLoader(options) {
|
|
117
|
+
if (isDeprecatedOptions(this.options)) {
|
|
118
|
+
return this.options.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
|
|
119
|
+
}
|
|
120
|
+
return getQueryLoader(this.viewer, this.options, options);
|
|
121
|
+
}
|
|
26
122
|
async queryRawCount() {
|
|
27
123
|
const idVisible = await this.idVisible();
|
|
28
124
|
if (!idVisible) {
|
|
29
125
|
return 0;
|
|
30
126
|
}
|
|
31
|
-
return
|
|
32
|
-
.createLoader(this.viewer.context)
|
|
33
|
-
.load(this.id);
|
|
127
|
+
return this.getCountLoader().load(this.id);
|
|
34
128
|
}
|
|
35
129
|
async queryAllRawCount() {
|
|
36
130
|
let count = 0;
|
|
@@ -44,16 +138,21 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
|
|
|
44
138
|
addID(this.options.src);
|
|
45
139
|
}
|
|
46
140
|
async loadRawData(infos, options) {
|
|
47
|
-
|
|
141
|
+
if (infos.length !== 1) {
|
|
142
|
+
throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
|
|
143
|
+
}
|
|
48
144
|
if (!options.orderby) {
|
|
49
|
-
options.orderby =
|
|
145
|
+
options.orderby = [
|
|
146
|
+
{
|
|
147
|
+
column: this.getSortCol(),
|
|
148
|
+
direction: "DESC",
|
|
149
|
+
},
|
|
150
|
+
];
|
|
50
151
|
}
|
|
51
152
|
if (!options.limit) {
|
|
52
|
-
options.limit = ent_1.
|
|
53
|
-
}
|
|
54
|
-
if (infos.length !== 1) {
|
|
55
|
-
throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
|
|
153
|
+
options.limit = (0, ent_1.getDefaultLimit)();
|
|
56
154
|
}
|
|
155
|
+
const loader = this.getQueryLoader(options);
|
|
57
156
|
const info = infos[0];
|
|
58
157
|
if (info.invalidated) {
|
|
59
158
|
this.edges.set(this.id, []);
|
|
@@ -66,8 +165,7 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
|
|
|
66
165
|
return edge.id;
|
|
67
166
|
}
|
|
68
167
|
async loadEntsFromEdges(id, rows) {
|
|
69
|
-
|
|
70
|
-
return Array.from(ents.values());
|
|
168
|
+
return (0, ent_1.applyPrivacyPolicyForRows)(this.viewer, rows, this.opts);
|
|
71
169
|
}
|
|
72
170
|
}
|
|
73
171
|
exports.CustomEdgeQueryBase = CustomEdgeQueryBase;
|
package/core/query/index.d.ts
CHANGED
package/core/query/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CustomEdgeQueryBase = exports.AssocEdgeQueryBase = exports.BaseEdgeQuery = void 0;
|
|
3
|
+
exports.CustomClauseQuery = exports.CustomEdgeQueryBase = exports.AssocEdgeQueryBase = exports.BaseEdgeQuery = void 0;
|
|
4
4
|
var query_1 = require("./query");
|
|
5
5
|
Object.defineProperty(exports, "BaseEdgeQuery", { enumerable: true, get: function () { return query_1.BaseEdgeQuery; } });
|
|
6
6
|
var assoc_query_1 = require("./assoc_query");
|
|
7
7
|
Object.defineProperty(exports, "AssocEdgeQueryBase", { enumerable: true, get: function () { return assoc_query_1.AssocEdgeQueryBase; } });
|
|
8
8
|
var custom_query_1 = require("./custom_query");
|
|
9
9
|
Object.defineProperty(exports, "CustomEdgeQueryBase", { enumerable: true, get: function () { return custom_query_1.CustomEdgeQueryBase; } });
|
|
10
|
+
var custom_clause_query_1 = require("./custom_clause_query");
|
|
11
|
+
Object.defineProperty(exports, "CustomClauseQuery", { enumerable: true, get: function () { return custom_clause_query_1.CustomClauseQuery; } });
|
package/core/query/query.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data, PrivacyPolicy } from "../base";
|
|
1
|
+
import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data, PrivacyPolicy, EdgeQueryableDataOptionsConfigureLoader } from "../base";
|
|
2
|
+
import { OrderBy } from "../query_impl";
|
|
2
3
|
export interface EdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> {
|
|
3
4
|
queryEdges(): Promise<TEdge[]>;
|
|
4
5
|
queryAllEdges(): Promise<Map<ID, TEdge[]>>;
|
|
@@ -20,7 +21,7 @@ export interface EdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends
|
|
|
20
21
|
}
|
|
21
22
|
export interface EdgeQueryFilter<T extends Data> {
|
|
22
23
|
filter?(id: ID, edges: T[]): T[];
|
|
23
|
-
query?(options: EdgeQueryableDataOptions): EdgeQueryableDataOptions
|
|
24
|
+
query?(options: EdgeQueryableDataOptions): EdgeQueryableDataOptions | Promise<EdgeQueryableDataOptions>;
|
|
24
25
|
paginationInfo?(id: ID): PaginationInfo | undefined;
|
|
25
26
|
}
|
|
26
27
|
export interface PaginationInfo {
|
|
@@ -29,9 +30,12 @@ export interface PaginationInfo {
|
|
|
29
30
|
startCursor: string;
|
|
30
31
|
endCursor: string;
|
|
31
32
|
}
|
|
33
|
+
interface EdgeQueryOptions {
|
|
34
|
+
cursorCol: string;
|
|
35
|
+
orderby: OrderBy;
|
|
36
|
+
}
|
|
32
37
|
export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> implements EdgeQuery<TSource, TDest, TEdge> {
|
|
33
38
|
viewer: Viewer;
|
|
34
|
-
private sortCol;
|
|
35
39
|
private filters;
|
|
36
40
|
private queryDispatched;
|
|
37
41
|
protected edges: Map<ID, TEdge[]>;
|
|
@@ -40,7 +44,12 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
|
|
|
40
44
|
protected genIDInfosToFetch: () => Promise<IDInfo[]>;
|
|
41
45
|
private idMap;
|
|
42
46
|
private idsToFetch;
|
|
43
|
-
|
|
47
|
+
private sortCol;
|
|
48
|
+
private cursorCol;
|
|
49
|
+
private edgeQueryOptions;
|
|
50
|
+
constructor(viewer: Viewer, sortCol: string, cursorCol: string);
|
|
51
|
+
constructor(viewer: Viewer, options: EdgeQueryOptions);
|
|
52
|
+
protected getSortCol(): string;
|
|
44
53
|
getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
|
|
45
54
|
abstract sourceEnt(id: ID): Promise<Ent | null>;
|
|
46
55
|
first(n: number, after?: string): this;
|
|
@@ -64,7 +73,11 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
|
|
|
64
73
|
protected abstract loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
|
|
65
74
|
protected abstract loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
|
|
66
75
|
private addID;
|
|
76
|
+
abstract getTableName(): string | Promise<string>;
|
|
67
77
|
protected genIDInfosToFetchImpl(): Promise<IDInfo[]>;
|
|
78
|
+
private _defaultEdgeQueryableOptions;
|
|
79
|
+
protected configureEdgeQueryableDataOptions(opts: EdgeQueryableDataOptionsConfigureLoader): void;
|
|
80
|
+
protected getDefaultEdgeQueryOptions(): Partial<Pick<import("../base").QueryableDataOptions, "clause" | "limit" | "orderby" | "disableTransformations">> | undefined;
|
|
68
81
|
private loadEdges;
|
|
69
82
|
getCursor(row: TEdge): string;
|
|
70
83
|
}
|
|
@@ -72,3 +85,4 @@ export interface IDInfo {
|
|
|
72
85
|
id: ID;
|
|
73
86
|
invalidated?: boolean;
|
|
74
87
|
}
|
|
88
|
+
export {};
|
package/core/query/query.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -27,6 +31,9 @@ const ent_1 = require("../ent");
|
|
|
27
31
|
const clause = __importStar(require("../clause"));
|
|
28
32
|
const memoizee_1 = __importDefault(require("memoizee"));
|
|
29
33
|
const privacy_1 = require("../privacy");
|
|
34
|
+
const uuid_1 = require("uuid");
|
|
35
|
+
const query_impl_1 = require("../query_impl");
|
|
36
|
+
const types_1 = require("util/types");
|
|
30
37
|
// TODO can we generalize EdgeQuery to support any clause
|
|
31
38
|
function assertPositive(n) {
|
|
32
39
|
if (n < 0) {
|
|
@@ -36,31 +43,32 @@ function assertPositive(n) {
|
|
|
36
43
|
function assertValidCursor(cursor, col) {
|
|
37
44
|
let decoded = Buffer.from(cursor, "base64").toString("ascii");
|
|
38
45
|
let parts = decoded.split(":");
|
|
46
|
+
// uuid, don't parse int since it tries to validate just first part
|
|
47
|
+
if ((0, uuid_1.validate)(parts[1])) {
|
|
48
|
+
return parts[1];
|
|
49
|
+
}
|
|
39
50
|
// invalid or unknown cursor. nothing to do here.
|
|
40
51
|
if (parts.length !== 2 || parts[0] !== col) {
|
|
41
52
|
throw new Error(`invalid cursor ${cursor} passed`);
|
|
42
53
|
}
|
|
43
|
-
// TODO
|
|
54
|
+
// TODO handle both cases... (time vs not) better
|
|
55
|
+
// TODO change this to only do the parseInt part if time...
|
|
56
|
+
// pass flag indicating if time?
|
|
44
57
|
const time = parseInt(parts[1], 10);
|
|
45
58
|
if (isNaN(time)) {
|
|
46
|
-
|
|
59
|
+
return parts[1];
|
|
47
60
|
}
|
|
48
61
|
return time;
|
|
49
62
|
}
|
|
63
|
+
const orderbyRegex = new RegExp(/([0-9a-z_]+)[ ]?([0-9a-z_]+)?/i);
|
|
50
64
|
class FirstFilter {
|
|
51
65
|
constructor(options) {
|
|
52
66
|
this.options = options;
|
|
53
67
|
this.pageMap = new Map();
|
|
54
68
|
assertPositive(options.limit);
|
|
55
|
-
|
|
56
|
-
throw new Error(`cannot specify before with a first filter`);
|
|
57
|
-
}
|
|
58
|
-
this.sortCol = options.sortCol || "time";
|
|
69
|
+
this.sortCol = options.sortCol;
|
|
59
70
|
if (options.after) {
|
|
60
|
-
this.offset = assertValidCursor(options.after,
|
|
61
|
-
}
|
|
62
|
-
if (this.options.sortColNotTime && !this.options.sortCol) {
|
|
63
|
-
throw new Error(`cannot specify sortColNotTime without specifying a sortCol`);
|
|
71
|
+
this.offset = assertValidCursor(options.after, options.cursorCol);
|
|
64
72
|
}
|
|
65
73
|
this.edgeQuery = options.query;
|
|
66
74
|
}
|
|
@@ -69,6 +77,8 @@ class FirstFilter {
|
|
|
69
77
|
const ret = edges.slice(0, this.options.limit);
|
|
70
78
|
this.pageMap.set(id, {
|
|
71
79
|
hasNextPage: true,
|
|
80
|
+
// hasPreviousPage always false even if there's a previous page because
|
|
81
|
+
// we shouldn't be querying in both directions at the same
|
|
72
82
|
hasPreviousPage: false,
|
|
73
83
|
startCursor: this.edgeQuery.getCursor(ret[0]),
|
|
74
84
|
endCursor: this.edgeQuery.getCursor(ret[ret.length - 1]),
|
|
@@ -82,24 +92,37 @@ class FirstFilter {
|
|
|
82
92
|
// so we'd need a way to indicate whether this is done in sql or not
|
|
83
93
|
return edges;
|
|
84
94
|
}
|
|
85
|
-
query(options) {
|
|
95
|
+
async query(options) {
|
|
86
96
|
// we fetch an extra one to see if we're at the end
|
|
87
97
|
const limit = this.options.limit + 1;
|
|
88
98
|
options.limit = limit;
|
|
89
|
-
// todo may not be desc
|
|
90
|
-
// and if asc
|
|
91
|
-
// clause below should switch to greater...
|
|
92
|
-
options.orderby = `${this.sortCol} DESC`;
|
|
93
99
|
// we sort by most recent first
|
|
94
100
|
// so when paging, we fetch afterCursor X
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
const less = this.options.orderby[0].direction === "DESC";
|
|
102
|
+
const orderby = this.options.orderby;
|
|
103
|
+
if (this.options.cursorCol !== this.sortCol) {
|
|
104
|
+
// we also sort cursor col in same direction. (direction doesn't matter)
|
|
105
|
+
orderby.push({
|
|
106
|
+
column: this.options.cursorCol,
|
|
107
|
+
direction: orderby[0].direction,
|
|
108
|
+
});
|
|
109
|
+
if (this.offset) {
|
|
110
|
+
const res = this.edgeQuery.getTableName();
|
|
111
|
+
const tableName = (0, types_1.isPromise)(res) ? await res : res;
|
|
112
|
+
// inner col time
|
|
113
|
+
options.clause = clause.PaginationMultipleColsSubQuery(this.sortCol, less ? "<" : ">", tableName, this.options.cursorCol, this.offset);
|
|
98
114
|
}
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
if (this.offset) {
|
|
118
|
+
let clauseFn = less ? clause.Less : clause.Greater;
|
|
119
|
+
let val = this.options.sortColTime
|
|
120
|
+
? new Date(this.offset).toISOString()
|
|
121
|
+
: this.offset;
|
|
122
|
+
options.clause = clauseFn(this.sortCol, val);
|
|
101
123
|
}
|
|
102
124
|
}
|
|
125
|
+
options.orderby = orderby;
|
|
103
126
|
return options;
|
|
104
127
|
}
|
|
105
128
|
// TODO?
|
|
@@ -112,15 +135,9 @@ class LastFilter {
|
|
|
112
135
|
this.options = options;
|
|
113
136
|
this.pageMap = new Map();
|
|
114
137
|
assertPositive(options.limit);
|
|
115
|
-
|
|
116
|
-
throw new Error(`cannot specify after with a last filter`);
|
|
117
|
-
}
|
|
118
|
-
this.sortCol = options.sortCol || "time";
|
|
138
|
+
this.sortCol = options.sortCol;
|
|
119
139
|
if (options.before) {
|
|
120
|
-
this.offset = assertValidCursor(options.before,
|
|
121
|
-
}
|
|
122
|
-
if (this.options.sortColNotTime && !this.options.sortCol) {
|
|
123
|
-
throw new Error(`cannot specify sortColNotTime without specifying a sortCol`);
|
|
140
|
+
this.offset = assertValidCursor(options.before, options.cursorCol);
|
|
124
141
|
}
|
|
125
142
|
this.edgeQuery = options.query;
|
|
126
143
|
}
|
|
@@ -137,11 +154,13 @@ class LastFilter {
|
|
|
137
154
|
}
|
|
138
155
|
}
|
|
139
156
|
else {
|
|
140
|
-
ret = edges.slice(
|
|
157
|
+
ret = edges.slice(0, this.options.limit);
|
|
141
158
|
}
|
|
142
159
|
if (edges.length > this.options.limit) {
|
|
143
160
|
this.pageMap.set(id, {
|
|
144
161
|
hasPreviousPage: true,
|
|
162
|
+
// hasNextPage always false even if there's a next page because
|
|
163
|
+
// we shouldn't be querying in both directions at the same
|
|
145
164
|
hasNextPage: false,
|
|
146
165
|
startCursor: this.edgeQuery.getCursor(ret[0]),
|
|
147
166
|
endCursor: this.edgeQuery.getCursor(ret[ret.length - 1]),
|
|
@@ -149,18 +168,33 @@ class LastFilter {
|
|
|
149
168
|
}
|
|
150
169
|
return ret;
|
|
151
170
|
}
|
|
152
|
-
query(options) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
options.orderby = `${this.sortCol} ASC`;
|
|
171
|
+
async query(options) {
|
|
172
|
+
const orderby = (0, query_impl_1.reverseOrderBy)(this.options.orderby);
|
|
173
|
+
const greater = orderby[0].direction === "ASC";
|
|
157
174
|
options.limit = this.options.limit + 1; // fetch an extra so we know if previous pag
|
|
158
|
-
if (this.options.
|
|
159
|
-
|
|
175
|
+
if (this.options.cursorCol !== this.sortCol) {
|
|
176
|
+
const res = this.edgeQuery.getTableName();
|
|
177
|
+
const tableName = (0, types_1.isPromise)(res) ? await res : res;
|
|
178
|
+
if (this.offset) {
|
|
179
|
+
// inner col time
|
|
180
|
+
options.clause = clause.PaginationMultipleColsSubQuery(this.sortCol, greater ? ">" : "<", tableName, this.options.cursorCol, this.offset);
|
|
181
|
+
}
|
|
182
|
+
// we also sort cursor col in same direction. (direction doesn't matter)
|
|
183
|
+
orderby.push({
|
|
184
|
+
column: this.options.cursorCol,
|
|
185
|
+
direction: orderby[0].direction,
|
|
186
|
+
});
|
|
160
187
|
}
|
|
161
188
|
else {
|
|
162
|
-
|
|
189
|
+
if (this.offset) {
|
|
190
|
+
let clauseFn = greater ? clause.Greater : clause.Less;
|
|
191
|
+
let val = this.options.sortColTime
|
|
192
|
+
? new Date(this.offset).toISOString()
|
|
193
|
+
: this.offset;
|
|
194
|
+
options.clause = clauseFn(this.sortCol, val);
|
|
195
|
+
}
|
|
163
196
|
}
|
|
197
|
+
options.orderby = orderby;
|
|
164
198
|
return options;
|
|
165
199
|
}
|
|
166
200
|
paginationInfo(id) {
|
|
@@ -168,9 +202,8 @@ class LastFilter {
|
|
|
168
202
|
}
|
|
169
203
|
}
|
|
170
204
|
class BaseEdgeQuery {
|
|
171
|
-
constructor(viewer,
|
|
205
|
+
constructor(viewer, sortColOrOptions, cursorColMaybe) {
|
|
172
206
|
this.viewer = viewer;
|
|
173
|
-
this.sortCol = sortCol;
|
|
174
207
|
this.filters = [];
|
|
175
208
|
this.edges = new Map();
|
|
176
209
|
this.pagination = new Map();
|
|
@@ -181,7 +214,7 @@ class BaseEdgeQuery {
|
|
|
181
214
|
return await this.querySingleEdge("queryEdges");
|
|
182
215
|
};
|
|
183
216
|
this.queryAllEdges = async () => {
|
|
184
|
-
return
|
|
217
|
+
return this.memoizedloadEdges();
|
|
185
218
|
};
|
|
186
219
|
this.queryIDs = async () => {
|
|
187
220
|
const edges = await this.querySingleEdge("queryIDs");
|
|
@@ -209,7 +242,7 @@ class BaseEdgeQuery {
|
|
|
209
242
|
};
|
|
210
243
|
this.queryEnts = async () => {
|
|
211
244
|
const edges = await this.querySingleEdge("queryEnts");
|
|
212
|
-
return
|
|
245
|
+
return this.loadEntsFromEdges("id", edges);
|
|
213
246
|
};
|
|
214
247
|
this.queryAllEnts = async () => {
|
|
215
248
|
// applies filters and then gets things after
|
|
@@ -226,9 +259,48 @@ class BaseEdgeQuery {
|
|
|
226
259
|
await Promise.all(promises);
|
|
227
260
|
return results;
|
|
228
261
|
};
|
|
262
|
+
let sortCol;
|
|
263
|
+
let cursorCol;
|
|
264
|
+
if (typeof sortColOrOptions === "string") {
|
|
265
|
+
sortCol = sortColOrOptions;
|
|
266
|
+
cursorCol = cursorColMaybe;
|
|
267
|
+
this.edgeQueryOptions = {
|
|
268
|
+
cursorCol,
|
|
269
|
+
orderby: [
|
|
270
|
+
{
|
|
271
|
+
column: sortCol,
|
|
272
|
+
direction: "DESC",
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
if (typeof sortColOrOptions.orderby === "string") {
|
|
279
|
+
sortCol = sortColOrOptions.orderby;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
// TODO this orderby isn't consistent and this logic needs to be changed anywhere that's using this and this.getSortCol()
|
|
283
|
+
sortCol = sortColOrOptions.orderby[0].column;
|
|
284
|
+
}
|
|
285
|
+
cursorCol = sortColOrOptions.cursorCol;
|
|
286
|
+
this.edgeQueryOptions = sortColOrOptions;
|
|
287
|
+
}
|
|
288
|
+
this.sortCol = sortCol;
|
|
289
|
+
let m = orderbyRegex.exec(sortCol);
|
|
290
|
+
if (!m) {
|
|
291
|
+
throw new Error(`invalid sort column ${sortCol}`);
|
|
292
|
+
}
|
|
293
|
+
this.sortCol = m[1];
|
|
294
|
+
if (m[2]) {
|
|
295
|
+
throw new Error(`passing direction in sort column is not supproted. use orderby`);
|
|
296
|
+
}
|
|
297
|
+
this.cursorCol = cursorCol;
|
|
229
298
|
this.memoizedloadEdges = (0, memoizee_1.default)(this.loadEdges.bind(this));
|
|
230
299
|
this.genIDInfosToFetch = (0, memoizee_1.default)(this.genIDInfosToFetchImpl.bind(this));
|
|
231
300
|
}
|
|
301
|
+
getSortCol() {
|
|
302
|
+
return this.sortCol;
|
|
303
|
+
}
|
|
232
304
|
getPrivacyPolicy() {
|
|
233
305
|
// default PrivacyPolicy is always allow. nothing to do here
|
|
234
306
|
return privacy_1.AlwaysAllowPrivacyPolicy;
|
|
@@ -239,6 +311,8 @@ class BaseEdgeQuery {
|
|
|
239
311
|
limit: n,
|
|
240
312
|
after,
|
|
241
313
|
sortCol: this.sortCol,
|
|
314
|
+
cursorCol: this.cursorCol,
|
|
315
|
+
orderby: this.edgeQueryOptions.orderby,
|
|
242
316
|
query: this,
|
|
243
317
|
}));
|
|
244
318
|
return this;
|
|
@@ -249,6 +323,8 @@ class BaseEdgeQuery {
|
|
|
249
323
|
limit: n,
|
|
250
324
|
before,
|
|
251
325
|
sortCol: this.sortCol,
|
|
326
|
+
cursorCol: this.cursorCol,
|
|
327
|
+
orderby: this.edgeQueryOptions.orderby,
|
|
252
328
|
query: this,
|
|
253
329
|
}));
|
|
254
330
|
return this;
|
|
@@ -290,21 +366,32 @@ class BaseEdgeQuery {
|
|
|
290
366
|
await this.loadRawIDs(this.addID.bind(this));
|
|
291
367
|
return applyPrivacyPolicyForEdgeQ(this.viewer, this, this.idsToFetch, this.idMap);
|
|
292
368
|
}
|
|
369
|
+
// FYI: this should be used sparingly.
|
|
370
|
+
// currently only exists so that disableTransformations can be configured by the developer
|
|
371
|
+
// so we're only exposing a partial API for now but maybe in the future we can expose
|
|
372
|
+
// the full API if there's a reason to use this that's not via filters
|
|
373
|
+
configureEdgeQueryableDataOptions(opts) {
|
|
374
|
+
this._defaultEdgeQueryableOptions = opts;
|
|
375
|
+
}
|
|
376
|
+
getDefaultEdgeQueryOptions() {
|
|
377
|
+
return this._defaultEdgeQueryableOptions;
|
|
378
|
+
}
|
|
293
379
|
async loadEdges() {
|
|
294
380
|
const idsInfo = await this.genIDInfosToFetch();
|
|
295
381
|
if (!this.filters.length) {
|
|
296
382
|
// if no filter, we add the firstN filter to ensure we get pagination info
|
|
297
|
-
this.first(ent_1.
|
|
383
|
+
this.first((0, ent_1.getDefaultLimit)());
|
|
298
384
|
}
|
|
299
|
-
let options = {};
|
|
385
|
+
let options = this._defaultEdgeQueryableOptions ?? {};
|
|
300
386
|
// TODO once we add a lot of complex filters, this needs to be more complicated
|
|
301
387
|
// e.g. commutative filters. what can be done in sql or combined together etc
|
|
302
388
|
// may need to bring sql mode or something back
|
|
303
|
-
this.filters
|
|
389
|
+
for (const filter of this.filters) {
|
|
304
390
|
if (filter.query) {
|
|
305
|
-
|
|
391
|
+
let res = filter.query(options);
|
|
392
|
+
options = (0, types_1.isPromise)(res) ? await res : res;
|
|
306
393
|
}
|
|
307
|
-
}
|
|
394
|
+
}
|
|
308
395
|
await this.loadRawData(idsInfo, options);
|
|
309
396
|
// no filters. nothing to do here.
|
|
310
397
|
if (!this.filters.length) {
|
|
@@ -331,17 +418,7 @@ class BaseEdgeQuery {
|
|
|
331
418
|
getCursor(row) {
|
|
332
419
|
return (0, ent_1.getCursor)({
|
|
333
420
|
row,
|
|
334
|
-
col: this.
|
|
335
|
-
conv: (datum) => {
|
|
336
|
-
if (datum instanceof Date) {
|
|
337
|
-
return datum.getTime();
|
|
338
|
-
}
|
|
339
|
-
// sqlite stores it as string and doesn't convert back
|
|
340
|
-
if (typeof datum === "string") {
|
|
341
|
-
return Date.parse(datum);
|
|
342
|
-
}
|
|
343
|
-
return datum;
|
|
344
|
-
},
|
|
421
|
+
col: this.cursorCol,
|
|
345
422
|
});
|
|
346
423
|
}
|
|
347
424
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { MockLogs } from "../../testutils/mock_log";
|
|
2
|
+
export declare function assocTests(ml: MockLogs, global?: boolean): void;
|