@snowtop/ent 0.1.0-alpha15 → 0.1.0-alpha151
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 +27 -16
- package/action/action.js +22 -7
- package/action/executor.d.ts +16 -3
- package/action/executor.js +90 -23
- package/action/experimental_action.d.ts +25 -16
- package/action/experimental_action.js +35 -9
- package/action/index.d.ts +3 -1
- package/action/index.js +7 -1
- package/action/operations.d.ts +125 -0
- package/action/operations.js +684 -0
- package/action/orchestrator.d.ts +38 -12
- package/action/orchestrator.js +427 -102
- 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 +52 -21
- package/core/base.js +7 -1
- package/core/clause.d.ts +95 -40
- package/core/clause.js +395 -64
- package/core/config.d.ts +15 -1
- package/core/config.js +10 -1
- package/core/const.d.ts +3 -0
- package/core/const.js +6 -0
- package/core/context.d.ts +4 -2
- package/core/context.js +20 -2
- package/core/convert.d.ts +1 -1
- package/core/date.js +1 -5
- package/core/db.d.ts +12 -8
- package/core/db.js +18 -8
- package/core/ent.d.ts +68 -94
- package/core/ent.js +538 -587
- package/core/global_schema.d.ts +7 -0
- package/core/global_schema.js +51 -0
- package/core/loaders/assoc_count_loader.d.ts +1 -0
- package/core/loaders/assoc_count_loader.js +10 -2
- package/core/loaders/assoc_edge_loader.d.ts +1 -1
- package/core/loaders/assoc_edge_loader.js +10 -13
- package/core/loaders/index.d.ts +1 -1
- package/core/loaders/index.js +1 -3
- package/core/loaders/index_loader.d.ts +3 -3
- package/core/loaders/loader.d.ts +2 -2
- package/core/loaders/loader.js +5 -5
- package/core/loaders/object_loader.d.ts +30 -9
- package/core/loaders/object_loader.js +225 -78
- package/core/loaders/query_loader.d.ts +6 -12
- package/core/loaders/query_loader.js +54 -13
- package/core/loaders/raw_count_loader.d.ts +1 -0
- package/core/loaders/raw_count_loader.js +7 -2
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +7 -6
- package/core/privacy.js +21 -25
- package/core/query/assoc_query.d.ts +3 -2
- package/core/query/assoc_query.js +9 -1
- package/core/query/custom_clause_query.d.ts +27 -0
- package/core/query/custom_clause_query.js +88 -0
- package/core/query/custom_query.d.ts +17 -2
- package/core/query/custom_query.js +88 -13
- package/core/query/index.d.ts +1 -0
- package/core/query/index.js +3 -1
- package/core/query/query.d.ts +15 -3
- package/core/query/query.js +128 -53
- package/core/query/shared_assoc_test.d.ts +2 -1
- package/core/query/shared_assoc_test.js +44 -54
- package/core/query/shared_test.d.ts +8 -1
- package/core/query/shared_test.js +532 -236
- package/core/viewer.d.ts +2 -0
- package/core/viewer.js +3 -1
- package/graphql/graphql.d.ts +52 -19
- package/graphql/graphql.js +174 -136
- package/graphql/graphql_field_helpers.d.ts +7 -1
- package/graphql/graphql_field_helpers.js +21 -1
- package/graphql/index.d.ts +2 -2
- package/graphql/index.js +3 -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 +18 -5
- package/index.js +30 -10
- package/package.json +18 -17
- package/parse_schema/parse.d.ts +31 -9
- package/parse_schema/parse.js +179 -32
- 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 +231 -71
- 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 +145 -34
- 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 +39 -43
- package/testutils/builder.js +75 -49
- 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} +244 -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 +16 -15
- 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 +43 -0
- package/testutils/fake_data/test_helpers.d.ts +11 -4
- package/testutils/fake_data/test_helpers.js +29 -13
- package/testutils/fake_data/user_query.d.ts +11 -4
- package/testutils/fake_data/user_query.js +54 -22
- 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 +25 -2
- package/tsc/ast.js +141 -17
- 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/graphql/enums.d.ts +0 -3
- package/graphql/enums.js +0 -25
- package/scripts/move_generated.js +0 -142
- package/scripts/transform_code.js +0 -113
- package/scripts/transform_schema.d.ts +0 -1
- /package/scripts/{move_generated.d.ts → migrate_v0.1.d.ts} +0 -0
- /package/scripts/{transform_code.d.ts → move_types.d.ts} +0 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultValue = exports.randomEmail = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const schema_1 = require("../../schema");
|
|
6
|
+
const schema_2 = require("../../schema");
|
|
7
|
+
function random() {
|
|
8
|
+
return Math.random().toString(16).substring(2);
|
|
9
|
+
}
|
|
10
|
+
function randomEmail(domain) {
|
|
11
|
+
domain = domain || "email.com";
|
|
12
|
+
return `test+${random()}@${domain}`;
|
|
13
|
+
}
|
|
14
|
+
exports.randomEmail = randomEmail;
|
|
15
|
+
function randomPhoneNumber() {
|
|
16
|
+
return `+1${Math.random().toString(10).substring(2, 11)}`;
|
|
17
|
+
}
|
|
18
|
+
function coinFlip() {
|
|
19
|
+
return Math.floor(Math.random() * 10) >= 5;
|
|
20
|
+
}
|
|
21
|
+
function specialType(typ, col) {
|
|
22
|
+
let list = m.get(typ.dbType);
|
|
23
|
+
if (list?.length) {
|
|
24
|
+
for (const l of list) {
|
|
25
|
+
let regex = [];
|
|
26
|
+
if (Array.isArray(l.regex)) {
|
|
27
|
+
regex = l.regex;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
regex = [l.regex];
|
|
31
|
+
}
|
|
32
|
+
for (const r of regex) {
|
|
33
|
+
if (r.test(col)) {
|
|
34
|
+
return l.newValue();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
function getDefaultValue(f, col, infos) {
|
|
42
|
+
if (f.defaultValueOnCreate) {
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
return f.defaultValueOnCreate();
|
|
45
|
+
}
|
|
46
|
+
// half the time, return null for nullable
|
|
47
|
+
if (f.nullable && coinFlip()) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const specialVal = specialType(f.type, col);
|
|
51
|
+
if (specialVal !== undefined) {
|
|
52
|
+
return specialVal;
|
|
53
|
+
}
|
|
54
|
+
return getValueForType(f.type, f, infos);
|
|
55
|
+
}
|
|
56
|
+
exports.getDefaultValue = getDefaultValue;
|
|
57
|
+
function getValueForType(typ, f, infos) {
|
|
58
|
+
switch (typ.dbType) {
|
|
59
|
+
case schema_1.DBType.UUID:
|
|
60
|
+
return (0, uuid_1.v4)();
|
|
61
|
+
case schema_1.DBType.Boolean:
|
|
62
|
+
return coinFlip();
|
|
63
|
+
case schema_1.DBType.Date:
|
|
64
|
+
return (0, schema_2.DateType)().format(new Date());
|
|
65
|
+
case schema_1.DBType.Time:
|
|
66
|
+
return (0, schema_2.TimeType)().format(new Date());
|
|
67
|
+
case schema_1.DBType.Timetz:
|
|
68
|
+
return (0, schema_2.TimetzType)().format(new Date());
|
|
69
|
+
case schema_1.DBType.Timestamp:
|
|
70
|
+
return (0, schema_2.TimestampType)().format(new Date());
|
|
71
|
+
case schema_1.DBType.Timestamptz:
|
|
72
|
+
return (0, schema_2.TimestamptzType)().format(new Date());
|
|
73
|
+
case schema_1.DBType.String:
|
|
74
|
+
return random();
|
|
75
|
+
case schema_1.DBType.Int:
|
|
76
|
+
return Math.floor(Math.random() * 100000000);
|
|
77
|
+
case schema_1.DBType.Float:
|
|
78
|
+
return Math.random() * 100000000;
|
|
79
|
+
case schema_1.DBType.Enum:
|
|
80
|
+
case schema_1.DBType.StringEnum:
|
|
81
|
+
if (typ.values) {
|
|
82
|
+
const idx = Math.floor(Math.random() * typ.values.length);
|
|
83
|
+
return typ.values[idx];
|
|
84
|
+
}
|
|
85
|
+
if (typ.enumMap) {
|
|
86
|
+
const vals = Object.values(typ.enumMap);
|
|
87
|
+
const idx = Math.floor(Math.random() * vals.length);
|
|
88
|
+
return vals[idx];
|
|
89
|
+
}
|
|
90
|
+
if (f.foreignKey) {
|
|
91
|
+
const schema = f.foreignKey.schema;
|
|
92
|
+
const col = f.foreignKey.column;
|
|
93
|
+
if (!infos) {
|
|
94
|
+
throw new Error(`infos required for enum with foreignKey`);
|
|
95
|
+
}
|
|
96
|
+
const info = infos.get(schema);
|
|
97
|
+
if (!info) {
|
|
98
|
+
throw new Error(`couldn't load data for schema ${schema}`);
|
|
99
|
+
}
|
|
100
|
+
if (!info.schema.dbRows) {
|
|
101
|
+
throw new Error(`no dbRows for schema ${schema}`);
|
|
102
|
+
}
|
|
103
|
+
const idx = Math.floor(Math.random() * info.schema.dbRows.length);
|
|
104
|
+
return info.schema.dbRows[idx][col];
|
|
105
|
+
}
|
|
106
|
+
throw new Error("TODO: enum without values not currently supported");
|
|
107
|
+
case schema_1.DBType.IntEnum:
|
|
108
|
+
const vals = Object.values(typ.intEnumMap);
|
|
109
|
+
const idx = Math.floor(Math.random() * vals.length);
|
|
110
|
+
return vals[idx];
|
|
111
|
+
case schema_1.DBType.BigInt:
|
|
112
|
+
return BigInt(Math.floor(Math.random() * 100000000));
|
|
113
|
+
case schema_1.DBType.JSONB:
|
|
114
|
+
// type as list
|
|
115
|
+
if (typ.listElemType?.dbType === schema_1.DBType.JSONB) {
|
|
116
|
+
const values = [];
|
|
117
|
+
for (let i = 0; i < 10; i++) {
|
|
118
|
+
values.push(getValueForType(typ.listElemType, f, infos));
|
|
119
|
+
}
|
|
120
|
+
if (!f.format) {
|
|
121
|
+
throw new Error("invalid format");
|
|
122
|
+
}
|
|
123
|
+
return f.format(values);
|
|
124
|
+
}
|
|
125
|
+
return (0, schema_2.JSONBType)().format({});
|
|
126
|
+
case schema_1.DBType.JSON:
|
|
127
|
+
return (0, schema_2.JSONType)().format({});
|
|
128
|
+
case schema_1.DBType.List:
|
|
129
|
+
// just do 10
|
|
130
|
+
const values = [];
|
|
131
|
+
for (let i = 0; i < 10; i++) {
|
|
132
|
+
values.push(getValueForType(f.type.listElemType, f.__getElemField(), infos));
|
|
133
|
+
}
|
|
134
|
+
if (!f.format) {
|
|
135
|
+
throw new Error("invalid format");
|
|
136
|
+
}
|
|
137
|
+
return f.format(values);
|
|
138
|
+
default:
|
|
139
|
+
throw new Error(`unsupported type ${typ.dbType}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const emailType = {
|
|
143
|
+
dbType: schema_1.DBType.String,
|
|
144
|
+
newValue: () => {
|
|
145
|
+
return (0, schema_2.StringType)().format(randomEmail().toLowerCase());
|
|
146
|
+
},
|
|
147
|
+
regex: /^email(_address)|_email$/,
|
|
148
|
+
};
|
|
149
|
+
const phoneType = {
|
|
150
|
+
dbType: schema_1.DBType.String,
|
|
151
|
+
newValue: () => {
|
|
152
|
+
return randomPhoneNumber();
|
|
153
|
+
},
|
|
154
|
+
regex: /^phone(_number)?|_phone$|_phone_number$/,
|
|
155
|
+
};
|
|
156
|
+
const passwordType = {
|
|
157
|
+
dbType: schema_1.DBType.String,
|
|
158
|
+
newValue: () => {
|
|
159
|
+
// we don't use password type because when we're generating so many rows, it's too slow...
|
|
160
|
+
return random();
|
|
161
|
+
},
|
|
162
|
+
regex: /^password/,
|
|
163
|
+
};
|
|
164
|
+
const firstNames = [
|
|
165
|
+
"Daenerys",
|
|
166
|
+
"Jon",
|
|
167
|
+
"Arya",
|
|
168
|
+
"Sansa",
|
|
169
|
+
"Eddard",
|
|
170
|
+
"Khal",
|
|
171
|
+
"Robb",
|
|
172
|
+
"Joffrey",
|
|
173
|
+
"Ramsay",
|
|
174
|
+
"Cersei",
|
|
175
|
+
"Bolton",
|
|
176
|
+
"Oberyn",
|
|
177
|
+
"Jojen",
|
|
178
|
+
"Petyr",
|
|
179
|
+
"Brienne",
|
|
180
|
+
"Ygritte",
|
|
181
|
+
"Missandei",
|
|
182
|
+
"Shae",
|
|
183
|
+
"Sandor",
|
|
184
|
+
"Theon",
|
|
185
|
+
"Catelyn",
|
|
186
|
+
"Gilly",
|
|
187
|
+
"Samwell",
|
|
188
|
+
"Jaime",
|
|
189
|
+
"Stannis",
|
|
190
|
+
"Tyene",
|
|
191
|
+
"Obara",
|
|
192
|
+
"Nymeria",
|
|
193
|
+
"Elia",
|
|
194
|
+
"Ellaria",
|
|
195
|
+
"Myrcella",
|
|
196
|
+
"Hodor",
|
|
197
|
+
"Osha",
|
|
198
|
+
"Meera",
|
|
199
|
+
"Davos",
|
|
200
|
+
"Gendry",
|
|
201
|
+
];
|
|
202
|
+
const lastNames = [
|
|
203
|
+
"Stark",
|
|
204
|
+
"Targaryen",
|
|
205
|
+
"Lannister",
|
|
206
|
+
"Drogo",
|
|
207
|
+
"Baratheon",
|
|
208
|
+
"Reed",
|
|
209
|
+
"Martell",
|
|
210
|
+
"Tyrell",
|
|
211
|
+
"Clegane",
|
|
212
|
+
"Baelish",
|
|
213
|
+
"Greyjoy",
|
|
214
|
+
"Tarly",
|
|
215
|
+
"Sand",
|
|
216
|
+
"Snow",
|
|
217
|
+
"Bolton",
|
|
218
|
+
"Frey",
|
|
219
|
+
"Tarth",
|
|
220
|
+
"Payne",
|
|
221
|
+
"Seaworth",
|
|
222
|
+
];
|
|
223
|
+
const firstNameType = {
|
|
224
|
+
dbType: schema_1.DBType.String,
|
|
225
|
+
newValue: () => {
|
|
226
|
+
let idx = Math.floor(firstNames.length * Math.random());
|
|
227
|
+
return firstNames[idx];
|
|
228
|
+
},
|
|
229
|
+
regex: /^first_?(name)?/,
|
|
230
|
+
};
|
|
231
|
+
const lastNameType = {
|
|
232
|
+
dbType: schema_1.DBType.String,
|
|
233
|
+
newValue: () => {
|
|
234
|
+
let idx = Math.floor(lastNames.length * Math.random());
|
|
235
|
+
return lastNames[idx];
|
|
236
|
+
},
|
|
237
|
+
regex: /^last_?(name)?/,
|
|
238
|
+
};
|
|
239
|
+
let types = [
|
|
240
|
+
phoneType,
|
|
241
|
+
emailType,
|
|
242
|
+
passwordType,
|
|
243
|
+
firstNameType,
|
|
244
|
+
lastNameType,
|
|
245
|
+
];
|
|
246
|
+
let m = new Map();
|
|
247
|
+
for (const type of types) {
|
|
248
|
+
let list = m.get(type.dbType) || [];
|
|
249
|
+
list.push(type);
|
|
250
|
+
m.set(type.dbType, list);
|
|
251
|
+
}
|
package/testutils/db_mock.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ export declare enum queryType {
|
|
|
18
18
|
UPDATE = 2,
|
|
19
19
|
BEGIN = 3,
|
|
20
20
|
COMMIT = 4,
|
|
21
|
-
ROLLBACK = 5
|
|
21
|
+
ROLLBACK = 5,
|
|
22
|
+
DELETE = 6
|
|
22
23
|
}
|
|
23
24
|
export interface queryStructure {
|
|
24
25
|
tableName?: string;
|
|
@@ -32,11 +33,14 @@ interface internalQueryStructure extends queryStructure {
|
|
|
32
33
|
suffix?: string;
|
|
33
34
|
setClause?: string;
|
|
34
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated
|
|
38
|
+
*/
|
|
35
39
|
export declare class QueryRecorder {
|
|
36
40
|
private static queries;
|
|
37
41
|
private static ids;
|
|
38
42
|
private static data;
|
|
39
|
-
|
|
43
|
+
static getQueryStructure(query: any): internalQueryStructure | null;
|
|
40
44
|
private static recordQuery;
|
|
41
45
|
static newID(): ID;
|
|
42
46
|
static getCurrentIDs(): ID[];
|
|
@@ -46,8 +50,16 @@ export declare class QueryRecorder {
|
|
|
46
50
|
static clear(): void;
|
|
47
51
|
static clearQueries(): void;
|
|
48
52
|
static getCurrentQueries(): queryOptions[];
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated will keep this since it's just using ml.logs
|
|
55
|
+
* which we still want around (I think) but we should eventually
|
|
56
|
+
* probably stop using this
|
|
57
|
+
*/
|
|
58
|
+
static validateQueryStructuresFromLogs(ml: MockLogs, expected: queryStructure[], opts?: {
|
|
59
|
+
skipSelect?: boolean;
|
|
60
|
+
flagBeginCommit?: boolean;
|
|
61
|
+
}): void;
|
|
62
|
+
private static validateQueryStructuresImpl;
|
|
51
63
|
static mockPool(pool: typeof Pool): void;
|
|
52
64
|
}
|
|
53
65
|
export {};
|
package/testutils/db_mock.js
CHANGED
|
@@ -29,7 +29,11 @@ var queryType;
|
|
|
29
29
|
queryType[queryType["BEGIN"] = 3] = "BEGIN";
|
|
30
30
|
queryType[queryType["COMMIT"] = 4] = "COMMIT";
|
|
31
31
|
queryType[queryType["ROLLBACK"] = 5] = "ROLLBACK";
|
|
32
|
+
queryType[queryType["DELETE"] = 6] = "DELETE";
|
|
32
33
|
})(queryType = exports.queryType || (exports.queryType = {}));
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated
|
|
36
|
+
*/
|
|
33
37
|
class QueryRecorder {
|
|
34
38
|
// TODO kill use AST or just throw away
|
|
35
39
|
static getQueryStructure(query) {
|
|
@@ -76,6 +80,36 @@ class QueryRecorder {
|
|
|
76
80
|
};
|
|
77
81
|
}
|
|
78
82
|
}
|
|
83
|
+
if (/^DELETE/.test(query)) {
|
|
84
|
+
// regex can't do returning
|
|
85
|
+
let execArray = /^DELETE FROM (.+) WHERE (.+) /.exec(query);
|
|
86
|
+
if (execArray) {
|
|
87
|
+
return {
|
|
88
|
+
tableName: execArray[1],
|
|
89
|
+
whereClause: execArray[2],
|
|
90
|
+
type: queryType.DELETE,
|
|
91
|
+
query: execArray[0],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (/^BEGIN/.test(query)) {
|
|
96
|
+
return {
|
|
97
|
+
type: queryType.BEGIN,
|
|
98
|
+
query: query,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (/^COMMIT/.test(query)) {
|
|
102
|
+
return {
|
|
103
|
+
type: queryType.COMMIT,
|
|
104
|
+
query: query,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (/^ROLLBACK/.test(query)) {
|
|
108
|
+
return {
|
|
109
|
+
type: queryType.ROLLBACK,
|
|
110
|
+
query: query,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
79
113
|
return null;
|
|
80
114
|
}
|
|
81
115
|
static recordQuery(query, values) {
|
|
@@ -131,7 +165,12 @@ class QueryRecorder {
|
|
|
131
165
|
static getCurrentQueries() {
|
|
132
166
|
return QueryRecorder.queries;
|
|
133
167
|
}
|
|
134
|
-
|
|
168
|
+
/**
|
|
169
|
+
* @deprecated will keep this since it's just using ml.logs
|
|
170
|
+
* which we still want around (I think) but we should eventually
|
|
171
|
+
* probably stop using this
|
|
172
|
+
*/
|
|
173
|
+
static validateQueryStructuresFromLogs(ml, expected, opts) {
|
|
135
174
|
const queries = ml.logs.map((log) => {
|
|
136
175
|
const qs = QueryRecorder.getQueryStructure(log.query);
|
|
137
176
|
if (!qs) {
|
|
@@ -142,12 +181,16 @@ class QueryRecorder {
|
|
|
142
181
|
qs,
|
|
143
182
|
};
|
|
144
183
|
});
|
|
145
|
-
QueryRecorder.
|
|
184
|
+
QueryRecorder.validateQueryStructuresImpl(expected, queries, opts);
|
|
146
185
|
}
|
|
147
|
-
static
|
|
148
|
-
if (skipSelect) {
|
|
186
|
+
static validateQueryStructuresImpl(expected, queries, opts) {
|
|
187
|
+
if (opts?.skipSelect) {
|
|
149
188
|
queries = queries.filter((query) => query.qs?.type !== queryType.SELECT);
|
|
150
189
|
}
|
|
190
|
+
if (!opts?.flagBeginCommit) {
|
|
191
|
+
queries = queries.filter((query) => query.qs?.type !== queryType.BEGIN &&
|
|
192
|
+
query.qs?.type !== queryType.COMMIT);
|
|
193
|
+
}
|
|
151
194
|
// console.log(queries, expected);
|
|
152
195
|
expect(queries.length).toBe(expected.length);
|
|
153
196
|
for (let i = 0; i < expected.length; i++) {
|
|
@@ -167,7 +210,7 @@ class QueryRecorder {
|
|
|
167
210
|
expect(query.values).toBe(undefined);
|
|
168
211
|
break;
|
|
169
212
|
case queryType.SELECT:
|
|
170
|
-
if (!skipSelect) {
|
|
213
|
+
if (!opts?.skipSelect) {
|
|
171
214
|
console.error("validating select query structure not supported yet");
|
|
172
215
|
}
|
|
173
216
|
// TODO INSERT and UPDATE tests here...
|
|
@@ -185,7 +228,9 @@ class QueryRecorder {
|
|
|
185
228
|
}
|
|
186
229
|
}
|
|
187
230
|
static mockPool(pool) {
|
|
188
|
-
const mockedPool = (0, jest_mock_1.mocked)(pool
|
|
231
|
+
const mockedPool = (0, jest_mock_1.mocked)(pool);
|
|
232
|
+
// @ts-ignore
|
|
233
|
+
// TODO what changed in mockImplementation?
|
|
189
234
|
mockedPool.mockImplementation(() => {
|
|
190
235
|
return {
|
|
191
236
|
totalCount: 1,
|
|
@@ -218,10 +263,8 @@ class QueryRecorder {
|
|
|
218
263
|
});
|
|
219
264
|
}
|
|
220
265
|
}
|
|
221
|
-
exports.QueryRecorder = QueryRecorder;
|
|
222
266
|
QueryRecorder.queries = [];
|
|
223
267
|
QueryRecorder.ids = [];
|
|
224
268
|
// we need pkeys when storing...
|
|
225
269
|
QueryRecorder.data = new Map();
|
|
226
|
-
|
|
227
|
-
process.env.DB_CONNECTION_STRING = "INVALID DATABASE";
|
|
270
|
+
exports.QueryRecorder = QueryRecorder;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DBTimeZone = void 0;
|
|
7
|
+
const luxon_1 = require("luxon");
|
|
8
|
+
const schema_1 = require("../schema");
|
|
9
|
+
const db_1 = __importDefault(require("../core/db"));
|
|
10
|
+
let dbCurrentZone = undefined;
|
|
11
|
+
class DBTimeZone {
|
|
12
|
+
static async getVal() {
|
|
13
|
+
if (dbCurrentZone !== undefined) {
|
|
14
|
+
return dbCurrentZone;
|
|
15
|
+
}
|
|
16
|
+
const r = await db_1.default.getInstance()
|
|
17
|
+
.getPool()
|
|
18
|
+
.query("SELECT current_setting('TIMEZONE');");
|
|
19
|
+
if (r.rows.length) {
|
|
20
|
+
dbCurrentZone = r.rows[0].current_setting;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
dbCurrentZone = null;
|
|
24
|
+
}
|
|
25
|
+
return dbCurrentZone;
|
|
26
|
+
}
|
|
27
|
+
static async getDateOffset(d) {
|
|
28
|
+
let zone = await DBTimeZone.getVal();
|
|
29
|
+
let dt = luxon_1.DateTime.fromJSDate(d);
|
|
30
|
+
if (zone) {
|
|
31
|
+
dt = dt.setZone(zone);
|
|
32
|
+
}
|
|
33
|
+
// use
|
|
34
|
+
const val = (0, schema_1.leftPad)(dt.get("offset") / 60);
|
|
35
|
+
if (val == "00") {
|
|
36
|
+
return "+00";
|
|
37
|
+
}
|
|
38
|
+
return val;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.DBTimeZone = DBTimeZone;
|
|
@@ -2,7 +2,7 @@ import { Express, RequestHandler } from "express";
|
|
|
2
2
|
import { Viewer } from "../../core/base";
|
|
3
3
|
import { GraphQLSchema } from "graphql";
|
|
4
4
|
import supertest from "supertest";
|
|
5
|
-
export
|
|
5
|
+
export type Option = [string, any] | [string, any, string];
|
|
6
6
|
interface queryConfig {
|
|
7
7
|
viewer?: Viewer;
|
|
8
8
|
init?: (app: Express) => void;
|
|
@@ -11,6 +11,12 @@ interface queryConfig {
|
|
|
11
11
|
headers?: object;
|
|
12
12
|
debugMode?: boolean;
|
|
13
13
|
args: {};
|
|
14
|
+
extraVariables?: {
|
|
15
|
+
[key: string]: {
|
|
16
|
+
graphqlType: string;
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
14
20
|
expectedStatus?: number;
|
|
15
21
|
expectedError?: string | RegExp;
|
|
16
22
|
callback?: (res: supertest.Response) => void;
|
|
@@ -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];
|
|
@@ -31,6 +35,7 @@ const graphql_1 = require("graphql");
|
|
|
31
35
|
const auth_1 = require("../../auth");
|
|
32
36
|
const supertest_1 = __importDefault(require("supertest"));
|
|
33
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const util_1 = require("util");
|
|
34
39
|
function server(config) {
|
|
35
40
|
const viewer = config.viewer;
|
|
36
41
|
if (viewer) {
|
|
@@ -45,6 +50,7 @@ function server(config) {
|
|
|
45
50
|
if (config.init) {
|
|
46
51
|
config.init(app);
|
|
47
52
|
}
|
|
53
|
+
// @ts-ignore something changed. come back
|
|
48
54
|
app.use(express_1.default.json());
|
|
49
55
|
let handlers = config.customHandlers || [];
|
|
50
56
|
handlers.push(async (req, res) => {
|
|
@@ -56,9 +62,11 @@ function server(config) {
|
|
|
56
62
|
request: req,
|
|
57
63
|
schema: config.schema,
|
|
58
64
|
contextFactory: async (executionContext) => {
|
|
65
|
+
// @ts-ignore something changed. come back
|
|
59
66
|
return (0, auth_1.buildContext)(req, res);
|
|
60
67
|
},
|
|
61
68
|
});
|
|
69
|
+
// @ts-ignore something changed. come back
|
|
62
70
|
await (0, graphql_helix_1.sendResult)(result, res);
|
|
63
71
|
});
|
|
64
72
|
app.use(config.graphQLPath || "/graphql", ...handlers);
|
|
@@ -108,17 +116,23 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
108
116
|
}
|
|
109
117
|
}
|
|
110
118
|
});
|
|
119
|
+
let variables = {
|
|
120
|
+
...config.args,
|
|
121
|
+
};
|
|
122
|
+
for (const k in config.extraVariables) {
|
|
123
|
+
variables[k] = config.extraVariables[k].value;
|
|
124
|
+
}
|
|
111
125
|
if (files.size) {
|
|
112
126
|
let ret = test
|
|
113
127
|
.post(config.graphQLPath || "/graphql")
|
|
114
128
|
.set(config.headers || {});
|
|
115
129
|
ret.field("operations", JSON.stringify({
|
|
116
130
|
query: query,
|
|
117
|
-
variables:
|
|
131
|
+
variables: variables,
|
|
118
132
|
}));
|
|
119
133
|
let m = {};
|
|
120
134
|
let idx = 0;
|
|
121
|
-
for (const [key
|
|
135
|
+
for (const [key] of files) {
|
|
122
136
|
m[idx] = [`variables.${key}`];
|
|
123
137
|
idx++;
|
|
124
138
|
}
|
|
@@ -141,15 +155,16 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
141
155
|
.set(config.headers || {})
|
|
142
156
|
.send({
|
|
143
157
|
query: query,
|
|
144
|
-
variables: JSON.stringify(
|
|
158
|
+
variables: JSON.stringify(variables),
|
|
145
159
|
}),
|
|
146
160
|
];
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
150
164
|
let fields;
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
const [typ] = getInnerType(fieldType, false);
|
|
166
|
+
if (typ instanceof graphql_1.GraphQLObjectType) {
|
|
167
|
+
fields = typ.getFields();
|
|
153
168
|
}
|
|
154
169
|
let topLevelTree = {};
|
|
155
170
|
options.forEach((option) => {
|
|
@@ -157,7 +172,7 @@ function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
|
157
172
|
let parts = [];
|
|
158
173
|
let match = fragmentRegex.exec(path);
|
|
159
174
|
if (match) {
|
|
160
|
-
// fragment, keep the part of the fragment e.g.
|
|
175
|
+
// fragment, keep the part of the fragment e.g. `...on User`, and then split the rest....
|
|
161
176
|
parts = [match[0], ...match[2].split(".")];
|
|
162
177
|
const typ = schema.getType(match[1]);
|
|
163
178
|
if (!typ) {
|
|
@@ -187,10 +202,11 @@ function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
|
187
202
|
}
|
|
188
203
|
// TODO this needs to be aware of paths etc so this part works for complicated
|
|
189
204
|
// cases but inlineFragmentRoot is a workaround for now.
|
|
190
|
-
function handleSubtree(obj, tree) {
|
|
205
|
+
function handleSubtree(obj, tree, parts) {
|
|
206
|
+
let parts2 = [...parts];
|
|
191
207
|
if (Array.isArray(obj)) {
|
|
192
208
|
for (const obj2 of obj) {
|
|
193
|
-
handleSubtree(obj2, tree);
|
|
209
|
+
handleSubtree(obj2, tree, parts2);
|
|
194
210
|
}
|
|
195
211
|
return;
|
|
196
212
|
}
|
|
@@ -199,28 +215,36 @@ function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
|
199
215
|
tree[key] = {};
|
|
200
216
|
}
|
|
201
217
|
if (typeof obj[key] === "object") {
|
|
202
|
-
|
|
203
|
-
|
|
218
|
+
let parts2 = [...parts, key];
|
|
219
|
+
if (!scalarFieldAtLeaf(parts2)) {
|
|
220
|
+
handleSubtree(obj[key], tree[key], parts2);
|
|
204
221
|
}
|
|
205
222
|
}
|
|
206
223
|
}
|
|
207
224
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (!subField) {
|
|
225
|
+
function scalarFieldAtLeaf(pathFromRoot) {
|
|
226
|
+
let root = fields;
|
|
227
|
+
if (!root) {
|
|
212
228
|
return false;
|
|
213
229
|
}
|
|
214
|
-
|
|
230
|
+
let subField;
|
|
231
|
+
for (const p of pathFromRoot) {
|
|
232
|
+
subField = root?.[p];
|
|
233
|
+
if (subField) {
|
|
234
|
+
[subField] = getInnerType(subField.type, false);
|
|
235
|
+
if (subField instanceof graphql_1.GraphQLObjectType) {
|
|
236
|
+
root = subField.getFields();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (!subField) {
|
|
215
241
|
return false;
|
|
216
242
|
}
|
|
217
|
-
|
|
218
|
-
const [typ, _] = getInnerType(subField.type, true);
|
|
219
|
-
return (0, graphql_1.isScalarType)(typ);
|
|
243
|
+
return (0, graphql_1.isScalarType)(subField) || (0, graphql_1.isEnumType)(subField);
|
|
220
244
|
}
|
|
221
245
|
if (i === parts.length - 1 && typeof option[1] === "object") {
|
|
222
|
-
if (!
|
|
223
|
-
handleSubtree(option[1], tree);
|
|
246
|
+
if (!scalarFieldAtLeaf(parts)) {
|
|
247
|
+
handleSubtree(option[1], tree, parts);
|
|
224
248
|
}
|
|
225
249
|
}
|
|
226
250
|
}
|
|
@@ -302,13 +326,18 @@ async function expectFromRoot(config, ...options) {
|
|
|
302
326
|
let fieldArgs = field.args;
|
|
303
327
|
let queryParams = [];
|
|
304
328
|
fieldArgs.forEach((fieldArg) => {
|
|
305
|
-
|
|
329
|
+
const arg = config.args[fieldArg.name];
|
|
306
330
|
// let the graphql runtime handle this (it may be optional for example)
|
|
307
331
|
if (arg === undefined) {
|
|
308
332
|
return;
|
|
309
333
|
}
|
|
310
334
|
queryParams.push(`$${fieldArg.name}: ${fieldArg.type}`);
|
|
311
335
|
});
|
|
336
|
+
// add extra variables in queryArgs...
|
|
337
|
+
for (const key in config.extraVariables) {
|
|
338
|
+
const v = config.extraVariables[key];
|
|
339
|
+
queryParams.push(`$${key}: ${v.graphqlType}`);
|
|
340
|
+
}
|
|
312
341
|
let params = [];
|
|
313
342
|
for (let key in config.args) {
|
|
314
343
|
params.push(`${key}: $${key}`);
|
|
@@ -347,7 +376,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
347
376
|
let [st, temp] = makeGraphQLRequest(config, q, fieldArgs);
|
|
348
377
|
const res = await temp.expect("Content-Type", /json/);
|
|
349
378
|
if (config.debugMode) {
|
|
350
|
-
console.log(res.body);
|
|
379
|
+
console.log((0, util_1.inspect)(res.body, false, 3));
|
|
351
380
|
}
|
|
352
381
|
// if there's a callback, let everything be done there and we're done
|
|
353
382
|
if (config.callback) {
|
|
@@ -389,8 +418,9 @@ async function expectFromRoot(config, ...options) {
|
|
|
389
418
|
}
|
|
390
419
|
}
|
|
391
420
|
await Promise.all(options.map(async (option) => {
|
|
392
|
-
|
|
393
|
-
|
|
421
|
+
const path = option[0];
|
|
422
|
+
const expected = option[1];
|
|
423
|
+
const alias = option[2];
|
|
394
424
|
let nullPath;
|
|
395
425
|
let nullParts = [];
|
|
396
426
|
let undefinedPath;
|
|
@@ -413,7 +443,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
413
443
|
}
|
|
414
444
|
}
|
|
415
445
|
}
|
|
416
|
-
let parts = splitPath(path);
|
|
446
|
+
let parts = splitPath(alias ?? path);
|
|
417
447
|
let current = result;
|
|
418
448
|
// possible to make this smarter and better
|
|
419
449
|
// e.g. when building up the tree above
|