@snowtop/ent 0.1.0-alpha13 → 0.1.0-alpha131
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 +33 -29
- package/action/action.js +22 -7
- package/action/executor.d.ts +3 -3
- package/action/executor.js +8 -3
- package/action/experimental_action.d.ts +32 -22
- package/action/experimental_action.js +35 -9
- package/action/index.d.ts +2 -0
- package/action/index.js +7 -1
- package/action/orchestrator.d.ts +32 -15
- package/action/orchestrator.js +249 -53
- package/action/privacy.d.ts +2 -2
- 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 +61 -37
- package/core/base.js +7 -1
- package/core/clause.d.ts +85 -40
- package/core/clause.js +375 -64
- package/core/config.d.ts +12 -1
- package/core/config.js +7 -1
- package/core/const.d.ts +3 -0
- package/core/const.js +6 -0
- package/core/context.d.ts +6 -4
- package/core/context.js +20 -2
- package/core/convert.d.ts +1 -1
- package/core/date.js +1 -5
- package/core/db.d.ts +11 -8
- package/core/db.js +20 -8
- package/core/ent.d.ts +86 -30
- package/core/ent.js +626 -197
- package/core/global_schema.d.ts +7 -0
- package/core/global_schema.js +51 -0
- package/core/loaders/assoc_count_loader.d.ts +3 -2
- package/core/loaders/assoc_count_loader.js +10 -2
- package/core/loaders/assoc_edge_loader.d.ts +2 -2
- package/core/loaders/assoc_edge_loader.js +8 -11
- 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 +32 -11
- package/core/loaders/object_loader.js +225 -78
- package/core/loaders/query_loader.d.ts +7 -13
- package/core/loaders/query_loader.js +52 -11
- package/core/loaders/raw_count_loader.d.ts +2 -2
- package/core/loaders/raw_count_loader.js +5 -1
- package/core/logger.d.ts +1 -1
- package/core/logger.js +1 -0
- package/core/privacy.d.ts +25 -24
- package/core/privacy.js +21 -25
- package/core/query/assoc_query.d.ts +7 -6
- 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 +84 -0
- package/core/query/custom_query.d.ts +20 -5
- package/core/query/custom_query.js +87 -12
- package/core/query/index.d.ts +1 -0
- package/core/query/index.js +3 -1
- package/core/query/query.d.ts +8 -4
- package/core/query/query.js +101 -53
- package/core/query/shared_assoc_test.d.ts +2 -1
- package/core/query/shared_assoc_test.js +35 -45
- package/core/query/shared_test.d.ts +8 -1
- package/core/query/shared_test.js +470 -236
- package/core/viewer.d.ts +3 -3
- package/core/viewer.js +1 -1
- package/graphql/graphql.d.ts +51 -19
- package/graphql/graphql.js +160 -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/edge_connection.d.ts +9 -9
- package/graphql/query/page_info.d.ts +1 -1
- 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 +6 -1
- package/imports/index.js +19 -4
- package/index.d.ts +13 -5
- package/index.js +21 -7
- package/package.json +17 -17
- package/parse_schema/parse.d.ts +31 -9
- package/parse_schema/parse.js +155 -13
- package/schema/base_schema.d.ts +7 -3
- package/schema/base_schema.js +10 -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 +5 -1
- package/schema/json_field.d.ts +16 -4
- package/schema/json_field.js +32 -2
- package/schema/schema.d.ts +89 -19
- package/schema/schema.js +11 -13
- 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 +10 -6
- package/scripts/custom_graphql.js +128 -31
- package/scripts/migrate_v0.1.js +36 -0
- package/scripts/move_types.js +120 -0
- package/scripts/read_schema.js +20 -5
- package/testutils/action/complex_schemas.d.ts +69 -0
- package/testutils/action/complex_schemas.js +398 -0
- package/testutils/builder.d.ts +41 -47
- package/testutils/builder.js +76 -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} +24 -8
- package/testutils/db/{test_db.js → temp_db.js} +182 -45
- 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 -7
- 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 +52 -23
- 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 +28 -12
- package/testutils/fake_data/user_query.d.ts +13 -6
- package/testutils/fake_data/user_query.js +54 -22
- package/testutils/fake_log.d.ts +3 -3
- 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 +181 -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
|
@@ -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];
|
|
@@ -22,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
27
|
};
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.getSchemaTable = exports.setupSqlite = exports.assoc_edge_table = exports.assoc_edge_config_table = exports.TempDB = exports.enumType = exports.table = exports.boolList = exports.dateList = exports.timetzList = exports.timeList = exports.timestamptzList = exports.timestampList = exports.uuidList = exports.integerList = exports.textList = exports.jsonb = exports.json = exports.float = exports.integer = exports.bool = exports.date = exports.timetz = exports.time = exports.timestamptz = exports.timestamp = exports.enumCol = exports.text = exports.uuid = exports.
|
|
29
|
+
exports.getColumnFromField = exports.getSchemaTable = exports.doSQLiteTestFromSchemas = exports.setupPostgres = exports.setupSqlite = exports.assoc_edge_table = exports.assoc_edge_config_table = exports.TempDB = exports.enumType = exports.table = exports.boolList = exports.dateList = exports.timetzList = exports.timeList = exports.timestamptzList = exports.timestampList = exports.uuidList = exports.integerList = exports.textList = exports.jsonb = exports.json = exports.float = exports.integer = exports.bool = exports.date = exports.timetz = exports.time = exports.timestamptz = exports.timestamp = exports.enumCol = exports.text = exports.uuid = exports.index = exports.check = exports.foreignKey = exports.primaryKey = void 0;
|
|
26
30
|
const pg_1 = require("pg");
|
|
27
31
|
const db_1 = __importStar(require("../../core/db"));
|
|
28
32
|
// this should only be used in tests so we expect to be able to import without shenanigans
|
|
@@ -32,6 +36,7 @@ const fs = __importStar(require("fs"));
|
|
|
32
36
|
const schema_1 = require("../../schema");
|
|
33
37
|
const snake_case_1 = require("snake-case");
|
|
34
38
|
const builder_1 = require("../builder");
|
|
39
|
+
const test_edge_global_schema_1 = require("../test_edge_global_schema");
|
|
35
40
|
function primaryKey(name, cols) {
|
|
36
41
|
return {
|
|
37
42
|
name: name,
|
|
@@ -50,15 +55,35 @@ function foreignKey(name, cols, fkey) {
|
|
|
50
55
|
};
|
|
51
56
|
}
|
|
52
57
|
exports.foreignKey = foreignKey;
|
|
53
|
-
function
|
|
58
|
+
function check(name, condition) {
|
|
54
59
|
return {
|
|
55
|
-
name
|
|
60
|
+
name,
|
|
56
61
|
generate() {
|
|
57
|
-
return `
|
|
62
|
+
return `CONSTRAINT ${name} CHECK(${condition})`;
|
|
58
63
|
},
|
|
59
64
|
};
|
|
60
65
|
}
|
|
61
|
-
exports.
|
|
66
|
+
exports.check = check;
|
|
67
|
+
function isPostCreateIndex(s) {
|
|
68
|
+
return (s.postCreate !== undefined &&
|
|
69
|
+
s.postCreate());
|
|
70
|
+
}
|
|
71
|
+
function index(tableName, cols, opts) {
|
|
72
|
+
const name = `${tableName}_${cols.join("_")}_idx`;
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
generate() {
|
|
76
|
+
if (opts?.unique && db_1.Dialect.SQLite === db_1.default.getDialect()) {
|
|
77
|
+
return `UNIQUE (${cols.join(",")})`;
|
|
78
|
+
}
|
|
79
|
+
return `CREATE ${opts?.unique ? "UNIQUE " : ""}INDEX ${name} ON ${tableName} USING ${opts?.type || "btree"} (${cols.join(",")});`;
|
|
80
|
+
},
|
|
81
|
+
postCreate() {
|
|
82
|
+
return db_1.Dialect.Postgres === db_1.default.getDialect() && !!opts?.unique;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
exports.index = index;
|
|
62
87
|
function uuid(name, opts) {
|
|
63
88
|
return {
|
|
64
89
|
name,
|
|
@@ -248,9 +273,24 @@ exports.boolList = boolList;
|
|
|
248
273
|
function table(name, ...items) {
|
|
249
274
|
let cols = [];
|
|
250
275
|
let constraints = [];
|
|
276
|
+
let indexes = [];
|
|
251
277
|
for (const item of items) {
|
|
252
278
|
if (item.datatype !== undefined) {
|
|
253
279
|
const col = item;
|
|
280
|
+
if (col.index) {
|
|
281
|
+
let opts = {
|
|
282
|
+
type: "btree",
|
|
283
|
+
};
|
|
284
|
+
if (col.index === true) {
|
|
285
|
+
opts = {
|
|
286
|
+
type: "btree",
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
opts = col.index;
|
|
291
|
+
}
|
|
292
|
+
indexes.push(index(name, [col.name], opts));
|
|
293
|
+
}
|
|
254
294
|
// add it as a constraint
|
|
255
295
|
if (col.foreignKey) {
|
|
256
296
|
constraints.push(foreignKey(`${name}_${col.name}_fkey`, [col.name], {
|
|
@@ -261,7 +301,12 @@ function table(name, ...items) {
|
|
|
261
301
|
cols.push(item);
|
|
262
302
|
}
|
|
263
303
|
else if (item.generate !== undefined) {
|
|
264
|
-
|
|
304
|
+
if (isPostCreateIndex(item) && item.postCreate()) {
|
|
305
|
+
indexes.push(item);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
constraints.push(item);
|
|
309
|
+
}
|
|
265
310
|
}
|
|
266
311
|
}
|
|
267
312
|
return {
|
|
@@ -278,7 +323,12 @@ function table(name, ...items) {
|
|
|
278
323
|
parts.push("PRIMARY KEY");
|
|
279
324
|
}
|
|
280
325
|
if (col.default !== undefined) {
|
|
281
|
-
|
|
326
|
+
if (db_1.Dialect.SQLite === db_1.default.getDialect()) {
|
|
327
|
+
parts.push(`DEFAULT "${col.default}"`);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
parts.push(`DEFAULT ${col.default}`);
|
|
331
|
+
}
|
|
282
332
|
}
|
|
283
333
|
if (col.unique) {
|
|
284
334
|
parts.push("UNIQUE");
|
|
@@ -288,6 +338,9 @@ function table(name, ...items) {
|
|
|
288
338
|
constraints.forEach((constraint) => schemaStr.push(constraint.generate()));
|
|
289
339
|
return `CREATE TABLE IF NOT EXISTS ${name} (\n ${schemaStr})`;
|
|
290
340
|
},
|
|
341
|
+
postCreate() {
|
|
342
|
+
return indexes.map((index) => index.generate());
|
|
343
|
+
},
|
|
291
344
|
drop() {
|
|
292
345
|
return `DROP TABLE IF EXISTS ${name}`;
|
|
293
346
|
},
|
|
@@ -311,29 +364,18 @@ function randomDB() {
|
|
|
311
364
|
// always ensure it starts with an alpha character
|
|
312
365
|
return "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)] + str;
|
|
313
366
|
}
|
|
314
|
-
function isDialect(dialect) {
|
|
315
|
-
return !Array.isArray(dialect);
|
|
316
|
-
}
|
|
317
367
|
class TempDB {
|
|
318
368
|
constructor(dialect, tables) {
|
|
319
369
|
this.tables = new Map();
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this.dialect = dialect;
|
|
323
|
-
if (tables) {
|
|
324
|
-
tbles = tables;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
this.dialect = db_1.Dialect.Postgres;
|
|
329
|
-
tbles = dialect;
|
|
330
|
-
}
|
|
331
|
-
tbles.forEach((table) => this.tables.set(table.name, table));
|
|
370
|
+
this.dialect = dialect;
|
|
371
|
+
this.setTables = tables;
|
|
332
372
|
}
|
|
333
373
|
getDialect() {
|
|
334
374
|
return this.dialect;
|
|
335
375
|
}
|
|
336
|
-
|
|
376
|
+
// NB: this won't be set until after beforeAll() is called since it depends on
|
|
377
|
+
// dialect being correctly set
|
|
378
|
+
__getTables() {
|
|
337
379
|
return this.tables;
|
|
338
380
|
}
|
|
339
381
|
async beforeAll(setupConnString = true) {
|
|
@@ -349,12 +391,17 @@ class TempDB {
|
|
|
349
391
|
this.db = randomDB();
|
|
350
392
|
await this.client.query(`CREATE DATABASE ${this.db}`);
|
|
351
393
|
if (setupConnString) {
|
|
394
|
+
delete process.env.DB_CONNECTION_STRING;
|
|
395
|
+
let connStr = "";
|
|
352
396
|
if (user && password) {
|
|
353
|
-
|
|
397
|
+
connStr = `postgres://${user}:${password}@localhost:5432/${this.db}`;
|
|
354
398
|
}
|
|
355
399
|
else {
|
|
356
|
-
|
|
400
|
+
connStr = `postgres://localhost/${this.db}?`;
|
|
357
401
|
}
|
|
402
|
+
db_1.default.initDB({
|
|
403
|
+
connectionString: connStr,
|
|
404
|
+
});
|
|
358
405
|
}
|
|
359
406
|
else {
|
|
360
407
|
// will probably be setup via loadConfig
|
|
@@ -375,12 +422,35 @@ class TempDB {
|
|
|
375
422
|
const filePath = process.env.DB_CONNECTION_STRING.substr(10);
|
|
376
423
|
this.sqlite = (0, better_sqlite3_1.default)(filePath);
|
|
377
424
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
425
|
+
if (this.setTables) {
|
|
426
|
+
let tables = [];
|
|
427
|
+
if (typeof this.setTables === "function") {
|
|
428
|
+
tables = this.setTables();
|
|
381
429
|
}
|
|
382
430
|
else {
|
|
383
|
-
this.
|
|
431
|
+
tables = this.setTables;
|
|
432
|
+
}
|
|
433
|
+
tables.forEach((table) => this.tables.set(table.name, table));
|
|
434
|
+
}
|
|
435
|
+
for (const [_, table] of this.tables) {
|
|
436
|
+
await this.createImpl(table);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async createImpl(table) {
|
|
440
|
+
if (this.dialect == db_1.Dialect.Postgres) {
|
|
441
|
+
await this.dbClient.query(table.create());
|
|
442
|
+
if (table.postCreate) {
|
|
443
|
+
for (const q of table.postCreate()) {
|
|
444
|
+
await this.dbClient.query(q);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
this.sqlite.exec(table.create());
|
|
450
|
+
if (table.postCreate) {
|
|
451
|
+
for (const q of table.postCreate()) {
|
|
452
|
+
this.sqlite.exec(q);
|
|
453
|
+
}
|
|
384
454
|
}
|
|
385
455
|
}
|
|
386
456
|
}
|
|
@@ -393,6 +463,9 @@ class TempDB {
|
|
|
393
463
|
async afterAll() {
|
|
394
464
|
if (this.dialect === db_1.Dialect.SQLite) {
|
|
395
465
|
this.sqlite.close();
|
|
466
|
+
if (!this.sqlite.memory) {
|
|
467
|
+
fs.rmSync(this.getSqliteClient().name);
|
|
468
|
+
}
|
|
396
469
|
return;
|
|
397
470
|
}
|
|
398
471
|
// end our connection to db
|
|
@@ -431,12 +504,7 @@ class TempDB {
|
|
|
431
504
|
if (this.tables.has(table.name)) {
|
|
432
505
|
throw new Error(`table with name ${table.name} already exists`);
|
|
433
506
|
}
|
|
434
|
-
|
|
435
|
-
await this.dbClient.query(table.create());
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
this.sqlite.exec(table.create());
|
|
439
|
-
}
|
|
507
|
+
await this.createImpl(table);
|
|
440
508
|
this.tables.set(table.name, table);
|
|
441
509
|
}
|
|
442
510
|
}
|
|
@@ -448,18 +516,26 @@ function assoc_edge_config_table() {
|
|
|
448
516
|
text("edge_type", { primaryKey: true }), text("edge_name"), bool("symmetric_edge", { default: "FALSE" }), text("inverse_edge_type", { nullable: true }), text("edge_table"), timestamptz("created_at"), timestamptz("updated_at"));
|
|
449
517
|
}
|
|
450
518
|
exports.assoc_edge_config_table = assoc_edge_config_table;
|
|
451
|
-
|
|
452
|
-
|
|
519
|
+
// if global flag is true, add any column from testEdgeGlobalSchema
|
|
520
|
+
// up to caller to set/clear that as needed
|
|
521
|
+
function assoc_edge_table(name, global) {
|
|
522
|
+
const t = table(name, uuid("id1"), text("id1_type"),
|
|
453
523
|
// same as in assoc_edge_config_table
|
|
454
524
|
text("edge_type"), uuid("id2"), text("id2_type"), timestamptz("time"), text("data", { nullable: true }), primaryKey(`${name}_pkey`, ["id1", "id2", "edge_type"]));
|
|
525
|
+
if (global) {
|
|
526
|
+
for (const k in test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields) {
|
|
527
|
+
const col = getColumnFromField(k, test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields[k], db_1.Dialect.Postgres);
|
|
528
|
+
t.columns.push(col);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return t;
|
|
455
532
|
}
|
|
456
533
|
exports.assoc_edge_table = assoc_edge_table;
|
|
457
534
|
function setupSqlite(connString, tables, opts) {
|
|
458
|
-
let tdb;
|
|
535
|
+
let tdb = new TempDB(db_1.Dialect.SQLite, tables);
|
|
459
536
|
beforeAll(async () => {
|
|
460
537
|
process.env.DB_CONNECTION_STRING = connString;
|
|
461
538
|
(0, config_1.loadConfig)();
|
|
462
|
-
tdb = new TempDB(db_1.Dialect.SQLite, tables());
|
|
463
539
|
await tdb.beforeAll();
|
|
464
540
|
const conn = db_1.default.getInstance().getConnection();
|
|
465
541
|
expect(conn.db.memory).toBe(false);
|
|
@@ -467,7 +543,7 @@ function setupSqlite(connString, tables, opts) {
|
|
|
467
543
|
if (!opts?.disableDeleteAfterEachTest) {
|
|
468
544
|
afterEach(async () => {
|
|
469
545
|
const client = await db_1.default.getInstance().getNewClient();
|
|
470
|
-
for (const [key, _] of tdb.
|
|
546
|
+
for (const [key, _] of tdb.__getTables()) {
|
|
471
547
|
const query = `delete from ${key}`;
|
|
472
548
|
if (isSyncClient(client))
|
|
473
549
|
if (client.execSync) {
|
|
@@ -481,17 +557,77 @@ function setupSqlite(connString, tables, opts) {
|
|
|
481
557
|
}
|
|
482
558
|
afterAll(async () => {
|
|
483
559
|
await tdb.afterAll();
|
|
484
|
-
|
|
560
|
+
delete process.env.DB_CONNECTION_STRING;
|
|
485
561
|
});
|
|
562
|
+
return tdb;
|
|
486
563
|
}
|
|
487
564
|
exports.setupSqlite = setupSqlite;
|
|
565
|
+
function setupPostgres(tables, opts) {
|
|
566
|
+
let tdb;
|
|
567
|
+
beforeAll(async () => {
|
|
568
|
+
tdb = new TempDB(db_1.Dialect.Postgres, tables());
|
|
569
|
+
await tdb.beforeAll();
|
|
570
|
+
});
|
|
571
|
+
// TODO need to fix this implementation...
|
|
572
|
+
if (!opts?.disableDeleteAfterEachTest) {
|
|
573
|
+
afterEach(async () => {
|
|
574
|
+
const client = await db_1.default.getInstance().getNewClient();
|
|
575
|
+
for (const [key, _] of tdb.__getTables()) {
|
|
576
|
+
const query = `delete from ${key}`;
|
|
577
|
+
await client.exec(query);
|
|
578
|
+
}
|
|
579
|
+
client.release();
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
afterAll(async () => {
|
|
583
|
+
await tdb.afterAll();
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
exports.setupPostgres = setupPostgres;
|
|
587
|
+
async function doSQLiteTestFromSchemas(schemas, doTest, db) {
|
|
588
|
+
const connString = `sqlite:///${db || randomDB()}.db`;
|
|
589
|
+
const tables = schemas.map((schema) => getSchemaTable(schema, db_1.Dialect.SQLite));
|
|
590
|
+
let tdb = new TempDB(db_1.Dialect.SQLite, tables);
|
|
591
|
+
process.env.DB_CONNECTION_STRING = connString;
|
|
592
|
+
(0, config_1.loadConfig)();
|
|
593
|
+
await tdb.beforeAll();
|
|
594
|
+
await doTest();
|
|
595
|
+
await tdb.afterAll();
|
|
596
|
+
delete process.env.DB_CONNECTION_STRING;
|
|
597
|
+
return tdb;
|
|
598
|
+
}
|
|
599
|
+
exports.doSQLiteTestFromSchemas = doSQLiteTestFromSchemas;
|
|
488
600
|
function getSchemaTable(schema, dialect) {
|
|
489
601
|
const fields = (0, schema_1.getFields)(schema);
|
|
490
|
-
const
|
|
602
|
+
const items = [];
|
|
491
603
|
for (const [fieldName, field] of fields) {
|
|
492
|
-
|
|
604
|
+
items.push(getColumnFromField(fieldName, field, dialect));
|
|
605
|
+
}
|
|
606
|
+
if (schema.constraints) {
|
|
607
|
+
for (const constraint of schema.constraints) {
|
|
608
|
+
switch (constraint.type) {
|
|
609
|
+
case schema_1.ConstraintType.PrimaryKey:
|
|
610
|
+
items.push(primaryKey(constraint.name, constraint.columns));
|
|
611
|
+
break;
|
|
612
|
+
case schema_1.ConstraintType.ForeignKey:
|
|
613
|
+
if (!constraint.fkey) {
|
|
614
|
+
throw new Error(`need 'fkey' field for foreign key constraint`);
|
|
615
|
+
}
|
|
616
|
+
items.push(foreignKey(constraint.name, constraint.columns, {
|
|
617
|
+
table: constraint.fkey.tableName,
|
|
618
|
+
cols: constraint.fkey.columns,
|
|
619
|
+
}));
|
|
620
|
+
break;
|
|
621
|
+
case schema_1.ConstraintType.Check:
|
|
622
|
+
if (!constraint.condition) {
|
|
623
|
+
throw new Error(`need 'condition' field for check constraint`);
|
|
624
|
+
}
|
|
625
|
+
items.push(check(constraint.name, constraint.condition));
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
493
629
|
}
|
|
494
|
-
return table((0, builder_1.getTableName)(schema), ...
|
|
630
|
+
return table((0, builder_1.getTableName)(schema), ...items);
|
|
495
631
|
}
|
|
496
632
|
exports.getSchemaTable = getSchemaTable;
|
|
497
633
|
function getColumnForDbType(t, dialect) {
|
|
@@ -549,6 +685,7 @@ function getColumnFromField(fieldName, f, dialect) {
|
|
|
549
685
|
return getColumn(fieldName, f, fn);
|
|
550
686
|
}
|
|
551
687
|
}
|
|
688
|
+
exports.getColumnFromField = getColumnFromField;
|
|
552
689
|
function getColumn(fieldName, f, col) {
|
|
553
690
|
return col(storageKey(fieldName, f), buildOpts(f));
|
|
554
691
|
}
|
|
@@ -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 {};
|