@snowtop/ent 0.1.0-alpha52 → 0.1.0-alpha56

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.
@@ -1,4 +1,4 @@
1
- import { Orchestrator } from "@snowtop/ent/action";
1
+ import { Orchestrator } from "./orchestrator";
2
2
  import { Viewer, Ent, Data } from "../core/base";
3
3
  import { Action, WriteOperation, Builder, Trigger, Observer, Changeset, Validator } from "./action";
4
4
  export interface ActionOptions<TEnt extends Ent<TViewer>, TViewer extends Viewer, TData extends Data, TExistingEnt extends TMaybleNullableEnt<TEnt> = MaybeNull<TEnt>> {
@@ -651,7 +651,6 @@ class Orchestrator {
651
651
  async validWithErrors() {
652
652
  return this.validate();
653
653
  }
654
- // TODO validWithErrors
655
654
  async build() {
656
655
  // validate everything first
657
656
  await this.validX();
package/core/clause.d.ts CHANGED
@@ -29,12 +29,38 @@ declare class compositeClause implements Clause {
29
29
  logValues(): any[];
30
30
  instanceKey(): string;
31
31
  }
32
+ /**
33
+ * creates a clause to determine if the given value is contained in the array stored in the column in the db
34
+ * only works with postgres gin indexes
35
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
36
+ */
37
+ export declare function PostgresArrayContainsValue(col: string, value: any): Clause;
38
+ /**
39
+ * creates a clause to determine if every item in the list is stored in the array stored in the column in the db
40
+ * only works with postgres gin indexes
41
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
42
+ */
43
+ export declare function PostgresArrayContains(col: string, value: any[]): Clause;
44
+ /**
45
+ * creates a clause to determine if the given value is NOT contained in the array stored in the column in the db
46
+ * only works with postgres gin indexes
47
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
48
+ */
49
+ export declare function PostgresArrayNotContainsValue(col: string, value: any): Clause;
50
+ /**
51
+ * creates a clause to determine if every item in the list is NOT stored in the array stored in the column in the db
52
+ * only works with postgres gin indexes
53
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
54
+ */
55
+ export declare function PostgresArrayNotContains(col: string, value: any[]): Clause;
56
+ /**
57
+ * @deprecated use PostgresArrayContainsValue
58
+ */
32
59
  export declare function ArrayEq(col: string, value: any): Clause;
60
+ /**
61
+ * @deprecated use PostgresNotArrayContains
62
+ */
33
63
  export declare function ArrayNotEq(col: string, value: any): Clause;
34
- export declare function ArrayGreater(col: string, value: any): Clause;
35
- export declare function ArrayLess(col: string, value: any): Clause;
36
- export declare function ArrayGreaterEq(col: string, value: any): Clause;
37
- export declare function ArrayLessEq(col: string, value: any): Clause;
38
64
  export declare function Eq(col: string, value: any): Clause;
39
65
  export declare function NotEq(col: string, value: any): Clause;
40
66
  export declare function Greater(col: string, value: any): simpleClause;
package/core/clause.js CHANGED
@@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
19
  return result;
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayLessEq = exports.ArrayGreaterEq = exports.ArrayLess = exports.ArrayGreater = exports.ArrayNotEq = exports.ArrayEq = void 0;
22
+ exports.sensitiveValue = exports.TsVectorWebsearchToTsQuery = exports.TsVectorPhraseToTsQuery = exports.TsVectorPlainToTsQuery = exports.TsVectorColTsQuery = exports.WebsearchToTsQuery = exports.PhraseToTsQuery = exports.PlainToTsQuery = exports.TsQuery = exports.In = exports.Or = exports.AndOptional = exports.And = exports.LessEq = exports.GreaterEq = exports.Less = exports.Greater = exports.NotEq = exports.Eq = exports.ArrayNotEq = exports.ArrayEq = exports.PostgresArrayNotContains = exports.PostgresArrayNotContainsValue = exports.PostgresArrayContains = exports.PostgresArrayContainsValue = void 0;
23
23
  const db_1 = __importStar(require("./db"));
24
24
  function isSensitive(val) {
25
25
  return (val !== null &&
@@ -148,6 +148,57 @@ class arraySimpleClause {
148
148
  return `${this.col}${this.op}${rawValue(this.value)}`;
149
149
  }
150
150
  }
151
+ class postgresArrayContains {
152
+ constructor(col, value, not) {
153
+ this.col = col;
154
+ this.value = value;
155
+ this.not = not;
156
+ }
157
+ clause(idx) {
158
+ if (db_1.default.getDialect() === db_1.Dialect.Postgres) {
159
+ if (this.not) {
160
+ return `NOT ${this.col} @> $${idx}`;
161
+ }
162
+ return `${this.col} @> $${idx}`;
163
+ }
164
+ throw new Error(`not supported`);
165
+ }
166
+ values() {
167
+ if (isSensitive(this.value)) {
168
+ return [`{${this.value.value()}}`];
169
+ }
170
+ return [`{${this.value}}`];
171
+ }
172
+ logValues() {
173
+ if (isSensitive(this.value)) {
174
+ return [this.value.logValue()];
175
+ }
176
+ return [this.value];
177
+ }
178
+ instanceKey() {
179
+ if (this.not) {
180
+ return `NOT:${this.col}@>${rawValue(this.value)}`;
181
+ }
182
+ return `${this.col}@>${rawValue(this.value)}`;
183
+ }
184
+ }
185
+ class postgresArrayContainsList extends postgresArrayContains {
186
+ constructor(col, value, not) {
187
+ super(col, value, not);
188
+ }
189
+ values() {
190
+ return [
191
+ `{${this.value
192
+ .map((v) => {
193
+ if (isSensitive(v)) {
194
+ return v.value();
195
+ }
196
+ return v;
197
+ })
198
+ .join(", ")}}`,
199
+ ];
200
+ }
201
+ }
151
202
  class inClause {
152
203
  constructor(col, value) {
153
204
  this.col = col;
@@ -298,31 +349,56 @@ class websearchTosQueryClause extends tsQueryClause {
298
349
  return "websearch_to_tsquery";
299
350
  }
300
351
  }
301
- // TODO we need to check sqlite version...
352
+ /**
353
+ * creates a clause to determine if the given value is contained in the array stored in the column in the db
354
+ * only works with postgres gin indexes
355
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
356
+ */
357
+ function PostgresArrayContainsValue(col, value) {
358
+ return new postgresArrayContains(col, value);
359
+ }
360
+ exports.PostgresArrayContainsValue = PostgresArrayContainsValue;
361
+ /**
362
+ * creates a clause to determine if every item in the list is stored in the array stored in the column in the db
363
+ * only works with postgres gin indexes
364
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
365
+ */
366
+ function PostgresArrayContains(col, value) {
367
+ return new postgresArrayContainsList(col, value);
368
+ }
369
+ exports.PostgresArrayContains = PostgresArrayContains;
370
+ /**
371
+ * creates a clause to determine if the given value is NOT contained in the array stored in the column in the db
372
+ * only works with postgres gin indexes
373
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
374
+ */
375
+ function PostgresArrayNotContainsValue(col, value) {
376
+ return new postgresArrayContains(col, value, true);
377
+ }
378
+ exports.PostgresArrayNotContainsValue = PostgresArrayNotContainsValue;
379
+ /**
380
+ * creates a clause to determine if every item in the list is NOT stored in the array stored in the column in the db
381
+ * only works with postgres gin indexes
382
+ * https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-GIN
383
+ */
384
+ function PostgresArrayNotContains(col, value) {
385
+ return new postgresArrayContainsList(col, value, true);
386
+ }
387
+ exports.PostgresArrayNotContains = PostgresArrayNotContains;
388
+ /**
389
+ * @deprecated use PostgresArrayContainsValue
390
+ */
302
391
  function ArrayEq(col, value) {
303
392
  return new arraySimpleClause(col, value, "=");
304
393
  }
305
394
  exports.ArrayEq = ArrayEq;
395
+ /**
396
+ * @deprecated use PostgresNotArrayContains
397
+ */
306
398
  function ArrayNotEq(col, value) {
307
399
  return new arraySimpleClause(col, value, "!=");
308
400
  }
309
401
  exports.ArrayNotEq = ArrayNotEq;
310
- function ArrayGreater(col, value) {
311
- return new arraySimpleClause(col, value, ">");
312
- }
313
- exports.ArrayGreater = ArrayGreater;
314
- function ArrayLess(col, value) {
315
- return new arraySimpleClause(col, value, "<");
316
- }
317
- exports.ArrayLess = ArrayLess;
318
- function ArrayGreaterEq(col, value) {
319
- return new arraySimpleClause(col, value, ">=");
320
- }
321
- exports.ArrayGreaterEq = ArrayGreaterEq;
322
- function ArrayLessEq(col, value) {
323
- return new arraySimpleClause(col, value, "<=");
324
- }
325
- exports.ArrayLessEq = ArrayLessEq;
326
402
  function Eq(col, value) {
327
403
  return new simpleClause(col, value, "=", new isNullClause(col));
328
404
  }
package/index.d.ts CHANGED
@@ -20,10 +20,10 @@ declare const query: {
20
20
  LessEq: typeof q.LessEq;
21
21
  ArrayEq: typeof q.ArrayEq;
22
22
  ArrayNotEq: typeof q.ArrayNotEq;
23
- ArrayGreater: typeof q.ArrayGreater;
24
- ArrayLess: typeof q.ArrayLess;
25
- ArrayGreaterEq: typeof q.ArrayGreaterEq;
26
- ArrayLessEq: typeof q.ArrayLessEq;
23
+ PostgresArrayContainsValue: typeof q.PostgresArrayContainsValue;
24
+ PostgresArrayContains: typeof q.PostgresArrayContains;
25
+ PostgresArrayNotContainsValue: typeof q.PostgresArrayNotContainsValue;
26
+ PostgresArrayNotContains: typeof q.PostgresArrayNotContains;
27
27
  TsQuery: typeof q.TsQuery;
28
28
  PlainToTsQuery: typeof q.PlainToTsQuery;
29
29
  PhraseToTsQuery: typeof q.PhraseToTsQuery;
package/index.js CHANGED
@@ -116,10 +116,10 @@ const query = {
116
116
  LessEq: q.LessEq,
117
117
  ArrayEq: q.ArrayEq,
118
118
  ArrayNotEq: q.ArrayNotEq,
119
- ArrayGreater: q.ArrayGreater,
120
- ArrayLess: q.ArrayLess,
121
- ArrayGreaterEq: q.ArrayGreaterEq,
122
- ArrayLessEq: q.ArrayLessEq,
119
+ PostgresArrayContainsValue: q.PostgresArrayContainsValue,
120
+ PostgresArrayContains: q.PostgresArrayContains,
121
+ PostgresArrayNotContainsValue: q.PostgresArrayNotContainsValue,
122
+ PostgresArrayNotContains: q.PostgresArrayNotContains,
123
123
  TsQuery: q.TsQuery,
124
124
  PlainToTsQuery: q.PlainToTsQuery,
125
125
  PhraseToTsQuery: q.PhraseToTsQuery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.1.0-alpha52",
3
+ "version": "0.1.0-alpha56",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/schema/field.js CHANGED
@@ -25,6 +25,7 @@ const snake_case_1 = require("snake-case");
25
25
  const db_1 = __importStar(require("../core/db"));
26
26
  const schema_1 = require("./schema");
27
27
  const util_1 = require("util");
28
+ const uuid_1 = require("uuid");
28
29
  class BaseField {
29
30
  logValue(val) {
30
31
  if (this.sensitive) {
@@ -92,6 +93,9 @@ class UUIDField extends BaseField {
92
93
  return val.placeholderID !== undefined;
93
94
  }
94
95
  async valid(val) {
96
+ if (typeof val === "string" && !(0, uuid_1.validate)(val)) {
97
+ return false;
98
+ }
95
99
  if (!this.options?.fieldEdge?.enforceSchema) {
96
100
  return true;
97
101
  }
@@ -642,6 +646,10 @@ class ListField extends BaseField {
642
646
  }
643
647
  postgresVal(val, jsonType) {
644
648
  if (!jsonType) {
649
+ // support empty strings in list
650
+ if (val === "") {
651
+ val = '"' + val + '"';
652
+ }
645
653
  return val;
646
654
  }
647
655
  return JSON.stringify(val);
@@ -271,6 +271,7 @@ export interface Index {
271
271
  columns: string[];
272
272
  unique?: boolean;
273
273
  fulltext?: FullText;
274
+ indexType?: "gin" | "btree";
274
275
  }
275
276
  export interface ForeignKeyInfo {
276
277
  tableName: string;
@@ -237,7 +237,9 @@ async function main() {
237
237
  (0, graphql_1.addCustomType)({
238
238
  importPath: MODULE_PATH,
239
239
  // for go tests...
240
- secondaryImportPath: "../graphql/scalars/time",
240
+ // TODO need a flag that only does this for go tests
241
+ // breaks when running locally sometimes...
242
+ // secondaryImportPath: "../graphql/scalars/time",
241
243
  type: "GraphQLTime",
242
244
  });
243
245
  (0, graphql_1.addCustomType)({
@@ -12,6 +12,7 @@ interface Column extends SchemaItem {
12
12
  primaryKey?: boolean;
13
13
  unique?: boolean;
14
14
  default?: string;
15
+ index?: boolean | indexOptions;
15
16
  foreignKey?: {
16
17
  table: string;
17
18
  col: string;
@@ -20,21 +21,29 @@ interface Column extends SchemaItem {
20
21
  interface Constraint extends SchemaItem {
21
22
  generate(): string;
22
23
  }
24
+ interface Index extends SchemaItem {
25
+ generate(): string;
26
+ }
23
27
  export interface CoreConcept {
24
28
  name: string;
25
29
  create(): string;
30
+ postCreate?(): string[];
26
31
  drop(): string;
27
32
  }
28
33
  export interface Table extends CoreConcept {
29
34
  columns: Column[];
30
35
  constraints?: Constraint[];
31
36
  }
32
- declare type options = Pick<Column, "nullable" | "primaryKey" | "default" | "foreignKey" | "unique">;
37
+ declare type options = Pick<Column, "nullable" | "primaryKey" | "default" | "foreignKey" | "unique" | "index">;
33
38
  export declare function primaryKey(name: string, cols: string[]): Constraint;
34
39
  export declare function foreignKey(name: string, cols: string[], fkey: {
35
40
  table: string;
36
41
  cols: string[];
37
42
  }): Constraint;
43
+ interface indexOptions {
44
+ type: string;
45
+ }
46
+ export declare function index(tableName: string, cols: string[], opts?: indexOptions): Index;
38
47
  export declare function uniqueIndex(name: string): Constraint;
39
48
  export declare function uuid(name: string, opts?: options): Column;
40
49
  export declare function text(name: string, opts?: options): Column;
@@ -72,6 +81,7 @@ export declare class TempDB {
72
81
  getDialect(): Dialect;
73
82
  getTables(): Map<string, CoreConcept>;
74
83
  beforeAll(setupConnString?: boolean): Promise<void>;
84
+ createImpl(table: CoreConcept): Promise<void>;
75
85
  getSqliteClient(): SqliteDatabase;
76
86
  getPostgresClient(): PGClient;
77
87
  afterAll(): Promise<void>;
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  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;
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.index = exports.foreignKey = exports.primaryKey = void 0;
26
26
  const pg_1 = require("pg");
27
27
  const db_1 = __importStar(require("../../core/db"));
28
28
  // this should only be used in tests so we expect to be able to import without shenanigans
@@ -50,6 +50,16 @@ function foreignKey(name, cols, fkey) {
50
50
  };
51
51
  }
52
52
  exports.foreignKey = foreignKey;
53
+ function index(tableName, cols, opts) {
54
+ const name = `${tableName}_${cols.join("_")}_idx`;
55
+ return {
56
+ name,
57
+ generate() {
58
+ return `CREATE INDEX ${name} ON ${tableName} USING ${opts?.type || "btree"} (${cols.join(",")});`;
59
+ },
60
+ };
61
+ }
62
+ exports.index = index;
53
63
  function uniqueIndex(name) {
54
64
  return {
55
65
  name: "",
@@ -248,9 +258,24 @@ exports.boolList = boolList;
248
258
  function table(name, ...items) {
249
259
  let cols = [];
250
260
  let constraints = [];
261
+ let indexes = [];
251
262
  for (const item of items) {
252
263
  if (item.datatype !== undefined) {
253
264
  const col = item;
265
+ if (col.index) {
266
+ let opts = {
267
+ type: "btree",
268
+ };
269
+ if (col.index === true) {
270
+ opts = {
271
+ type: "btree",
272
+ };
273
+ }
274
+ else {
275
+ opts = col.index;
276
+ }
277
+ indexes.push(index(name, [col.name], opts));
278
+ }
254
279
  // add it as a constraint
255
280
  if (col.foreignKey) {
256
281
  constraints.push(foreignKey(`${name}_${col.name}_fkey`, [col.name], {
@@ -288,6 +313,9 @@ function table(name, ...items) {
288
313
  constraints.forEach((constraint) => schemaStr.push(constraint.generate()));
289
314
  return `CREATE TABLE IF NOT EXISTS ${name} (\n ${schemaStr})`;
290
315
  },
316
+ postCreate() {
317
+ return indexes.map((index) => index.generate());
318
+ },
291
319
  drop() {
292
320
  return `DROP TABLE IF EXISTS ${name}`;
293
321
  },
@@ -376,11 +404,24 @@ class TempDB {
376
404
  this.sqlite = (0, better_sqlite3_1.default)(filePath);
377
405
  }
378
406
  for (const [_, table] of this.tables) {
379
- if (this.dialect == db_1.Dialect.Postgres) {
380
- await this.dbClient.query(table.create());
407
+ await this.createImpl(table);
408
+ }
409
+ }
410
+ async createImpl(table) {
411
+ if (this.dialect == db_1.Dialect.Postgres) {
412
+ await this.dbClient.query(table.create());
413
+ if (table.postCreate) {
414
+ for (const q of table.postCreate()) {
415
+ await this.dbClient.query(q);
416
+ }
381
417
  }
382
- else {
383
- this.sqlite.exec(table.create());
418
+ }
419
+ else {
420
+ this.sqlite.exec(table.create());
421
+ if (table.postCreate) {
422
+ for (const q of table.postCreate()) {
423
+ this.sqlite.exec(q);
424
+ }
384
425
  }
385
426
  }
386
427
  }
@@ -431,12 +472,7 @@ class TempDB {
431
472
  if (this.tables.has(table.name)) {
432
473
  throw new Error(`table with name ${table.name} already exists`);
433
474
  }
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
- }
475
+ await this.createImpl(table);
440
476
  this.tables.set(table.name, table);
441
477
  }
442
478
  }