@snowtop/ent 0.1.0-alpha14 → 0.1.0-alpha141

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.
Files changed (169) hide show
  1. package/action/action.d.ts +27 -16
  2. package/action/action.js +22 -7
  3. package/action/executor.d.ts +16 -3
  4. package/action/executor.js +88 -21
  5. package/action/experimental_action.d.ts +25 -16
  6. package/action/experimental_action.js +35 -9
  7. package/action/index.d.ts +3 -1
  8. package/action/index.js +7 -1
  9. package/action/operations.d.ts +125 -0
  10. package/action/operations.js +684 -0
  11. package/action/orchestrator.d.ts +34 -11
  12. package/action/orchestrator.js +355 -92
  13. package/action/relative_value.d.ts +47 -0
  14. package/action/relative_value.js +125 -0
  15. package/action/transaction.d.ts +10 -0
  16. package/action/transaction.js +23 -0
  17. package/auth/auth.d.ts +1 -1
  18. package/core/base.d.ts +51 -21
  19. package/core/base.js +7 -1
  20. package/core/clause.d.ts +85 -40
  21. package/core/clause.js +375 -64
  22. package/core/config.d.ts +12 -1
  23. package/core/config.js +7 -1
  24. package/core/const.d.ts +3 -0
  25. package/core/const.js +6 -0
  26. package/core/context.d.ts +4 -2
  27. package/core/context.js +20 -2
  28. package/core/convert.d.ts +1 -1
  29. package/core/date.js +1 -5
  30. package/core/db.d.ts +12 -8
  31. package/core/db.js +18 -8
  32. package/core/ent.d.ts +66 -93
  33. package/core/ent.js +517 -577
  34. package/core/global_schema.d.ts +7 -0
  35. package/core/global_schema.js +51 -0
  36. package/core/loaders/assoc_count_loader.d.ts +1 -0
  37. package/core/loaders/assoc_count_loader.js +10 -2
  38. package/core/loaders/assoc_edge_loader.d.ts +1 -1
  39. package/core/loaders/assoc_edge_loader.js +8 -11
  40. package/core/loaders/index.d.ts +1 -1
  41. package/core/loaders/index.js +1 -3
  42. package/core/loaders/index_loader.d.ts +3 -3
  43. package/core/loaders/loader.d.ts +2 -2
  44. package/core/loaders/loader.js +5 -5
  45. package/core/loaders/object_loader.d.ts +30 -9
  46. package/core/loaders/object_loader.js +225 -78
  47. package/core/loaders/query_loader.d.ts +6 -12
  48. package/core/loaders/query_loader.js +52 -11
  49. package/core/loaders/raw_count_loader.js +5 -1
  50. package/core/logger.d.ts +1 -1
  51. package/core/logger.js +1 -0
  52. package/core/privacy.d.ts +7 -6
  53. package/core/privacy.js +21 -25
  54. package/core/query/assoc_query.d.ts +3 -2
  55. package/core/query/assoc_query.js +9 -1
  56. package/core/query/custom_clause_query.d.ts +27 -0
  57. package/core/query/custom_clause_query.js +84 -0
  58. package/core/query/custom_query.d.ts +17 -2
  59. package/core/query/custom_query.js +87 -12
  60. package/core/query/index.d.ts +1 -0
  61. package/core/query/index.js +3 -1
  62. package/core/query/query.d.ts +7 -3
  63. package/core/query/query.js +101 -53
  64. package/core/query/shared_assoc_test.d.ts +2 -1
  65. package/core/query/shared_assoc_test.js +35 -45
  66. package/core/query/shared_test.d.ts +8 -1
  67. package/core/query/shared_test.js +470 -236
  68. package/core/viewer.js +1 -1
  69. package/graphql/graphql.d.ts +52 -19
  70. package/graphql/graphql.js +174 -136
  71. package/graphql/graphql_field_helpers.d.ts +7 -1
  72. package/graphql/graphql_field_helpers.js +21 -1
  73. package/graphql/index.d.ts +2 -2
  74. package/graphql/index.js +3 -5
  75. package/graphql/query/connection_type.d.ts +9 -9
  76. package/graphql/query/shared_assoc_test.js +1 -1
  77. package/graphql/query/shared_edge_connection.js +1 -19
  78. package/graphql/scalars/orderby_direction.d.ts +2 -0
  79. package/graphql/scalars/orderby_direction.js +15 -0
  80. package/imports/dataz/example1/_auth.js +128 -47
  81. package/imports/dataz/example1/_viewer.js +87 -39
  82. package/imports/index.d.ts +6 -1
  83. package/imports/index.js +19 -4
  84. package/index.d.ts +14 -5
  85. package/index.js +26 -10
  86. package/package.json +18 -17
  87. package/parse_schema/parse.d.ts +31 -9
  88. package/parse_schema/parse.js +156 -13
  89. package/schema/base_schema.d.ts +9 -3
  90. package/schema/base_schema.js +12 -0
  91. package/schema/field.d.ts +78 -21
  92. package/schema/field.js +231 -71
  93. package/schema/index.d.ts +2 -2
  94. package/schema/index.js +5 -1
  95. package/schema/json_field.d.ts +16 -4
  96. package/schema/json_field.js +32 -2
  97. package/schema/schema.d.ts +96 -19
  98. package/schema/schema.js +11 -13
  99. package/schema/struct_field.d.ts +15 -3
  100. package/schema/struct_field.js +117 -22
  101. package/schema/union_field.d.ts +1 -1
  102. package/scripts/custom_compiler.js +10 -6
  103. package/scripts/custom_graphql.js +142 -31
  104. package/scripts/migrate_v0.1.js +36 -0
  105. package/scripts/move_types.js +120 -0
  106. package/scripts/read_schema.js +20 -5
  107. package/testutils/action/complex_schemas.d.ts +69 -0
  108. package/testutils/action/complex_schemas.js +405 -0
  109. package/testutils/builder.d.ts +39 -43
  110. package/testutils/builder.js +75 -49
  111. package/testutils/db/fixture.d.ts +10 -0
  112. package/testutils/db/fixture.js +26 -0
  113. package/testutils/db/{test_db.d.ts → temp_db.d.ts} +25 -8
  114. package/testutils/db/{test_db.js → temp_db.js} +224 -47
  115. package/testutils/db/value.d.ts +7 -0
  116. package/testutils/db/value.js +251 -0
  117. package/testutils/db_mock.d.ts +16 -4
  118. package/testutils/db_mock.js +52 -7
  119. package/testutils/db_time_zone.d.ts +4 -0
  120. package/testutils/db_time_zone.js +41 -0
  121. package/testutils/ent-graphql-tests/index.d.ts +7 -1
  122. package/testutils/ent-graphql-tests/index.js +52 -23
  123. package/testutils/fake_comms.js +1 -1
  124. package/testutils/fake_data/const.d.ts +2 -1
  125. package/testutils/fake_data/const.js +3 -0
  126. package/testutils/fake_data/fake_contact.d.ts +7 -3
  127. package/testutils/fake_data/fake_contact.js +13 -7
  128. package/testutils/fake_data/fake_event.d.ts +4 -1
  129. package/testutils/fake_data/fake_event.js +7 -6
  130. package/testutils/fake_data/fake_tag.d.ts +36 -0
  131. package/testutils/fake_data/fake_tag.js +89 -0
  132. package/testutils/fake_data/fake_user.d.ts +8 -5
  133. package/testutils/fake_data/fake_user.js +16 -15
  134. package/testutils/fake_data/index.js +5 -1
  135. package/testutils/fake_data/internal.d.ts +2 -0
  136. package/testutils/fake_data/internal.js +7 -1
  137. package/testutils/fake_data/tag_query.d.ts +13 -0
  138. package/testutils/fake_data/tag_query.js +43 -0
  139. package/testutils/fake_data/test_helpers.d.ts +11 -4
  140. package/testutils/fake_data/test_helpers.js +28 -12
  141. package/testutils/fake_data/user_query.d.ts +11 -4
  142. package/testutils/fake_data/user_query.js +54 -22
  143. package/testutils/fake_log.js +1 -1
  144. package/testutils/parse_sql.d.ts +6 -0
  145. package/testutils/parse_sql.js +16 -2
  146. package/testutils/test_edge_global_schema.d.ts +15 -0
  147. package/testutils/test_edge_global_schema.js +62 -0
  148. package/testutils/write.d.ts +2 -2
  149. package/testutils/write.js +33 -7
  150. package/tsc/ast.d.ts +25 -2
  151. package/tsc/ast.js +141 -17
  152. package/tsc/compilerOptions.js +5 -1
  153. package/tsc/move_generated.d.ts +1 -0
  154. package/tsc/move_generated.js +164 -0
  155. package/tsc/transform.d.ts +22 -0
  156. package/tsc/transform.js +181 -0
  157. package/tsc/transform_action.d.ts +22 -0
  158. package/tsc/transform_action.js +183 -0
  159. package/tsc/transform_ent.d.ts +17 -0
  160. package/tsc/transform_ent.js +60 -0
  161. package/tsc/transform_schema.d.ts +27 -0
  162. package/{scripts → tsc}/transform_schema.js +146 -117
  163. package/graphql/enums.d.ts +0 -3
  164. package/graphql/enums.js +0 -25
  165. package/scripts/move_generated.js +0 -142
  166. package/scripts/transform_code.js +0 -113
  167. package/scripts/transform_schema.d.ts +0 -1
  168. /package/scripts/{move_generated.d.ts → migrate_v0.1.d.ts} +0 -0
  169. /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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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.uniqueIndex = exports.foreignKey = exports.primaryKey = void 0;
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,49 @@ function foreignKey(name, cols, fkey) {
50
55
  };
51
56
  }
52
57
  exports.foreignKey = foreignKey;
53
- function uniqueIndex(name) {
58
+ function check(name, condition) {
59
+ return {
60
+ name,
61
+ generate() {
62
+ return `CONSTRAINT ${name} CHECK(${condition})`;
63
+ },
64
+ };
65
+ }
66
+ exports.check = check;
67
+ function unique(name, cols, tableName) {
68
+ return {
69
+ name,
70
+ generate() {
71
+ if (db_1.Dialect.SQLite === db_1.default.getDialect()) {
72
+ return `UNIQUE (${cols.join(",")})`;
73
+ }
74
+ return `ALTER TABLE ${tableName} ADD CONSTRAINT ${name} UNIQUE (${cols.join(", ")});`;
75
+ },
76
+ postCreate() {
77
+ return db_1.Dialect.Postgres === db_1.default.getDialect();
78
+ },
79
+ };
80
+ }
81
+ function isPostCreateIndex(s) {
82
+ return (s.postCreate !== undefined &&
83
+ s.postCreate());
84
+ }
85
+ function index(tableName, cols, opts) {
86
+ const name = `${tableName}_${cols.join("_")}_idx`;
54
87
  return {
55
- name: "",
88
+ name,
56
89
  generate() {
57
- return `UNIQUE (${name})`;
90
+ if (opts?.unique && db_1.Dialect.SQLite === db_1.default.getDialect()) {
91
+ return `UNIQUE (${cols.join(",")})`;
92
+ }
93
+ return `CREATE ${opts?.unique ? "UNIQUE " : ""}INDEX ${name} ON ${tableName} USING ${opts?.type || "btree"} (${cols.join(",")});`;
94
+ },
95
+ postCreate() {
96
+ return db_1.Dialect.Postgres === db_1.default.getDialect() && !!opts?.unique;
58
97
  },
59
98
  };
60
99
  }
61
- exports.uniqueIndex = uniqueIndex;
100
+ exports.index = index;
62
101
  function uuid(name, opts) {
63
102
  return {
64
103
  name,
@@ -248,9 +287,24 @@ exports.boolList = boolList;
248
287
  function table(name, ...items) {
249
288
  let cols = [];
250
289
  let constraints = [];
290
+ let indexes = [];
251
291
  for (const item of items) {
252
292
  if (item.datatype !== undefined) {
253
293
  const col = item;
294
+ if (col.index) {
295
+ let opts = {
296
+ type: "btree",
297
+ };
298
+ if (col.index === true) {
299
+ opts = {
300
+ type: "btree",
301
+ };
302
+ }
303
+ else {
304
+ opts = col.index;
305
+ }
306
+ indexes.push(index(name, [col.name], opts));
307
+ }
254
308
  // add it as a constraint
255
309
  if (col.foreignKey) {
256
310
  constraints.push(foreignKey(`${name}_${col.name}_fkey`, [col.name], {
@@ -261,7 +315,12 @@ function table(name, ...items) {
261
315
  cols.push(item);
262
316
  }
263
317
  else if (item.generate !== undefined) {
264
- constraints.push(item);
318
+ if (isPostCreateIndex(item) && item.postCreate()) {
319
+ indexes.push(item);
320
+ }
321
+ else {
322
+ constraints.push(item);
323
+ }
265
324
  }
266
325
  }
267
326
  return {
@@ -278,7 +337,12 @@ function table(name, ...items) {
278
337
  parts.push("PRIMARY KEY");
279
338
  }
280
339
  if (col.default !== undefined) {
281
- parts.push(`DEFAULT ${col.default}`);
340
+ if (db_1.Dialect.SQLite === db_1.default.getDialect()) {
341
+ parts.push(`DEFAULT "${col.default}"`);
342
+ }
343
+ else {
344
+ parts.push(`DEFAULT ${col.default}`);
345
+ }
282
346
  }
283
347
  if (col.unique) {
284
348
  parts.push("UNIQUE");
@@ -288,6 +352,9 @@ function table(name, ...items) {
288
352
  constraints.forEach((constraint) => schemaStr.push(constraint.generate()));
289
353
  return `CREATE TABLE IF NOT EXISTS ${name} (\n ${schemaStr})`;
290
354
  },
355
+ postCreate() {
356
+ return indexes.map((index) => index.generate());
357
+ },
291
358
  drop() {
292
359
  return `DROP TABLE IF EXISTS ${name}`;
293
360
  },
@@ -311,29 +378,18 @@ function randomDB() {
311
378
  // always ensure it starts with an alpha character
312
379
  return "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)] + str;
313
380
  }
314
- function isDialect(dialect) {
315
- return !Array.isArray(dialect);
316
- }
317
381
  class TempDB {
318
382
  constructor(dialect, tables) {
319
383
  this.tables = new Map();
320
- let tbles = [];
321
- if (isDialect(dialect)) {
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));
384
+ this.dialect = dialect;
385
+ this.setTables = tables;
332
386
  }
333
387
  getDialect() {
334
388
  return this.dialect;
335
389
  }
336
- getTables() {
390
+ // NB: this won't be set until after beforeAll() is called since it depends on
391
+ // dialect being correctly set
392
+ __getTables() {
337
393
  return this.tables;
338
394
  }
339
395
  async beforeAll(setupConnString = true) {
@@ -349,12 +405,21 @@ class TempDB {
349
405
  this.db = randomDB();
350
406
  await this.client.query(`CREATE DATABASE ${this.db}`);
351
407
  if (setupConnString) {
408
+ delete process.env.DB_CONNECTION_STRING;
409
+ let connStr = "";
352
410
  if (user && password) {
353
- process.env.DB_CONNECTION_STRING = `postgres://${user}:${password}@localhost:5432/${this.db}`;
411
+ connStr = `postgres://${user}:${password}@localhost:5432/${this.db}`;
354
412
  }
355
413
  else {
356
- process.env.DB_CONNECTION_STRING = `postgres://localhost/${this.db}?`;
414
+ connStr = `postgres://localhost/${this.db}?`;
357
415
  }
416
+ db_1.default.initDB({
417
+ connectionString: connStr,
418
+ cfg: {
419
+ max: 100,
420
+ idleTimeoutMillis: 100,
421
+ },
422
+ });
358
423
  }
359
424
  else {
360
425
  // will probably be setup via loadConfig
@@ -375,12 +440,35 @@ class TempDB {
375
440
  const filePath = process.env.DB_CONNECTION_STRING.substr(10);
376
441
  this.sqlite = (0, better_sqlite3_1.default)(filePath);
377
442
  }
378
- for (const [_, table] of this.tables) {
379
- if (this.dialect == db_1.Dialect.Postgres) {
380
- await this.dbClient.query(table.create());
443
+ if (this.setTables) {
444
+ let tables = [];
445
+ if (typeof this.setTables === "function") {
446
+ tables = this.setTables();
381
447
  }
382
448
  else {
383
- this.sqlite.exec(table.create());
449
+ tables = this.setTables;
450
+ }
451
+ tables.forEach((table) => this.tables.set(table.name, table));
452
+ }
453
+ for (const [_, table] of this.tables) {
454
+ await this.createImpl(table);
455
+ }
456
+ }
457
+ async createImpl(table) {
458
+ if (this.dialect == db_1.Dialect.Postgres) {
459
+ await this.dbClient.query(table.create());
460
+ if (table.postCreate) {
461
+ for (const q of table.postCreate()) {
462
+ await this.dbClient.query(q);
463
+ }
464
+ }
465
+ }
466
+ else {
467
+ this.sqlite.exec(table.create());
468
+ if (table.postCreate) {
469
+ for (const q of table.postCreate()) {
470
+ this.sqlite.exec(q);
471
+ }
384
472
  }
385
473
  }
386
474
  }
@@ -393,6 +481,9 @@ class TempDB {
393
481
  async afterAll() {
394
482
  if (this.dialect === db_1.Dialect.SQLite) {
395
483
  this.sqlite.close();
484
+ if (!this.sqlite.memory) {
485
+ fs.rmSync(this.getSqliteClient().name);
486
+ }
396
487
  return;
397
488
  }
398
489
  // end our connection to db
@@ -401,6 +492,7 @@ class TempDB {
401
492
  await db_1.default.getInstance().endPool();
402
493
  // drop db
403
494
  await this.client.query(`DROP DATABASE ${this.db}`);
495
+ // console.log(this.db);
404
496
  await this.client.end();
405
497
  }
406
498
  getDB() {
@@ -431,12 +523,7 @@ class TempDB {
431
523
  if (this.tables.has(table.name)) {
432
524
  throw new Error(`table with name ${table.name} already exists`);
433
525
  }
434
- if (this.dialect === db_1.Dialect.Postgres) {
435
- await this.dbClient.query(table.create());
436
- }
437
- else {
438
- this.sqlite.exec(table.create());
439
- }
526
+ await this.createImpl(table);
440
527
  this.tables.set(table.name, table);
441
528
  }
442
529
  }
@@ -448,18 +535,38 @@ function assoc_edge_config_table() {
448
535
  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
536
  }
450
537
  exports.assoc_edge_config_table = assoc_edge_config_table;
451
- function assoc_edge_table(name) {
452
- return table(name, uuid("id1"), text("id1_type"),
453
- // same as in assoc_edge_config_table
454
- text("edge_type"), uuid("id2"), text("id2_type"), timestamptz("time"), text("data", { nullable: true }), primaryKey(`${name}_pkey`, ["id1", "id2", "edge_type"]));
538
+ // if global flag is true, add any column from testEdgeGlobalSchema
539
+ // up to caller to set/clear that as needed
540
+ function assoc_edge_table(name, global, unique_edge) {
541
+ const items = [
542
+ uuid("id1"),
543
+ text("id1_type"),
544
+ // same as in assoc_edge_config_table
545
+ text("edge_type"),
546
+ uuid("id2"),
547
+ text("id2_type"),
548
+ timestamptz("time"),
549
+ text("data", { nullable: true }),
550
+ primaryKey(`${name}_pkey`, ["id1", "id2", "edge_type"]),
551
+ ];
552
+ if (unique_edge) {
553
+ items.push(unique(`${name}_unique_id1_edge_type`, ["id1", "edge_type"], name));
554
+ }
555
+ const t = table(name, ...items);
556
+ if (global) {
557
+ for (const k in test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields) {
558
+ const col = getColumnFromField(k, test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields[k], db_1.Dialect.Postgres);
559
+ t.columns.push(col);
560
+ }
561
+ }
562
+ return t;
455
563
  }
456
564
  exports.assoc_edge_table = assoc_edge_table;
457
565
  function setupSqlite(connString, tables, opts) {
458
- let tdb;
566
+ let tdb = new TempDB(db_1.Dialect.SQLite, tables);
459
567
  beforeAll(async () => {
460
568
  process.env.DB_CONNECTION_STRING = connString;
461
569
  (0, config_1.loadConfig)();
462
- tdb = new TempDB(db_1.Dialect.SQLite, tables());
463
570
  await tdb.beforeAll();
464
571
  const conn = db_1.default.getInstance().getConnection();
465
572
  expect(conn.db.memory).toBe(false);
@@ -467,7 +574,7 @@ function setupSqlite(connString, tables, opts) {
467
574
  if (!opts?.disableDeleteAfterEachTest) {
468
575
  afterEach(async () => {
469
576
  const client = await db_1.default.getInstance().getNewClient();
470
- for (const [key, _] of tdb.getTables()) {
577
+ for (const [key, _] of tdb.__getTables()) {
471
578
  const query = `delete from ${key}`;
472
579
  if (isSyncClient(client))
473
580
  if (client.execSync) {
@@ -481,17 +588,83 @@ function setupSqlite(connString, tables, opts) {
481
588
  }
482
589
  afterAll(async () => {
483
590
  await tdb.afterAll();
484
- fs.rmSync(tdb.getSqliteClient().name);
591
+ delete process.env.DB_CONNECTION_STRING;
485
592
  });
593
+ return tdb;
486
594
  }
487
595
  exports.setupSqlite = setupSqlite;
596
+ function setupPostgres(tables, opts) {
597
+ let tdb;
598
+ beforeAll(async () => {
599
+ tdb = new TempDB(db_1.Dialect.Postgres, tables());
600
+ await tdb.beforeAll();
601
+ });
602
+ // TODO need to fix this implementation...
603
+ if (!opts?.disableDeleteAfterEachTest) {
604
+ afterEach(async () => {
605
+ const client = await db_1.default.getInstance().getNewClient();
606
+ for (const [key, _] of tdb.__getTables()) {
607
+ const query = `delete from ${key}`;
608
+ await client.exec(query);
609
+ }
610
+ client.release();
611
+ });
612
+ }
613
+ afterAll(async () => {
614
+ await tdb.afterAll();
615
+ });
616
+ }
617
+ exports.setupPostgres = setupPostgres;
618
+ async function doSQLiteTestFromSchemas(schemas, doTest, db) {
619
+ const connString = `sqlite:///${db || randomDB()}.db`;
620
+ const tables = schemas.map((schema) => getSchemaTable(schema, db_1.Dialect.SQLite));
621
+ let tdb = new TempDB(db_1.Dialect.SQLite, tables);
622
+ process.env.DB_CONNECTION_STRING = connString;
623
+ (0, config_1.loadConfig)();
624
+ await tdb.beforeAll();
625
+ await doTest();
626
+ await tdb.afterAll();
627
+ delete process.env.DB_CONNECTION_STRING;
628
+ return tdb;
629
+ }
630
+ exports.doSQLiteTestFromSchemas = doSQLiteTestFromSchemas;
488
631
  function getSchemaTable(schema, dialect) {
489
632
  const fields = (0, schema_1.getFields)(schema);
490
- const columns = [];
633
+ const items = [];
491
634
  for (const [fieldName, field] of fields) {
492
- columns.push(getColumnFromField(fieldName, field, dialect));
635
+ items.push(getColumnFromField(fieldName, field, dialect));
493
636
  }
494
- return table((0, builder_1.getTableName)(schema), ...columns);
637
+ const tableName = (0, builder_1.getTableName)(schema);
638
+ if (schema.constraints) {
639
+ for (const constraint of schema.constraints) {
640
+ switch (constraint.type) {
641
+ case schema_1.ConstraintType.PrimaryKey:
642
+ items.push(primaryKey(constraint.name, constraint.columns));
643
+ break;
644
+ case schema_1.ConstraintType.ForeignKey:
645
+ if (!constraint.fkey) {
646
+ throw new Error(`need 'fkey' field for foreign key constraint`);
647
+ }
648
+ items.push(foreignKey(constraint.name, constraint.columns, {
649
+ table: constraint.fkey.tableName,
650
+ cols: constraint.fkey.columns,
651
+ }));
652
+ break;
653
+ case schema_1.ConstraintType.Check:
654
+ if (!constraint.condition) {
655
+ throw new Error(`need 'condition' field for check constraint`);
656
+ }
657
+ items.push(check(constraint.name, constraint.condition));
658
+ break;
659
+ case schema_1.ConstraintType.Unique:
660
+ items.push(unique(constraint.name, constraint.columns, tableName));
661
+ break;
662
+ default:
663
+ throw new Error(`unknown constraint type ${constraint.type}`);
664
+ }
665
+ }
666
+ }
667
+ return table(tableName, ...items);
495
668
  }
496
669
  exports.getSchemaTable = getSchemaTable;
497
670
  function getColumnForDbType(t, dialect) {
@@ -549,6 +722,7 @@ function getColumnFromField(fieldName, f, dialect) {
549
722
  return getColumn(fieldName, f, fn);
550
723
  }
551
724
  }
725
+ exports.getColumnFromField = getColumnFromField;
552
726
  function getColumn(fieldName, f, col) {
553
727
  return col(storageKey(fieldName, f), buildOpts(f));
554
728
  }
@@ -567,6 +741,9 @@ function buildOpts(f) {
567
741
  if (f.serverDefault) {
568
742
  ret.default = f.serverDefault;
569
743
  }
744
+ if (f.unique) {
745
+ ret.unique = true;
746
+ }
570
747
  return ret;
571
748
  }
572
749
  function storageKey(fieldName, f) {
@@ -0,0 +1,7 @@
1
+ import { Field, Schema } from "../../schema";
2
+ export declare function randomEmail(domain?: string): string;
3
+ interface Info {
4
+ schema: Schema;
5
+ }
6
+ export declare function getDefaultValue(f: Field, col: string, infos?: Map<string, Info>): any;
7
+ export {};
@@ -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
+ }