@snowtop/ent 0.1.0-alpha99 → 0.1.0
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 +8 -1
- package/action/executor.d.ts +16 -3
- package/action/executor.js +83 -27
- package/action/index.d.ts +2 -1
- package/action/operations.d.ts +126 -0
- package/action/operations.js +686 -0
- package/action/orchestrator.d.ts +22 -8
- package/action/orchestrator.js +278 -67
- package/core/base.d.ts +34 -24
- package/core/clause.d.ts +62 -79
- package/core/clause.js +77 -5
- package/core/config.d.ts +5 -1
- package/core/config.js +3 -0
- package/core/const.d.ts +3 -0
- package/core/const.js +6 -0
- package/core/context.d.ts +4 -3
- package/core/context.js +2 -1
- package/core/db.d.ts +1 -0
- package/core/db.js +7 -7
- package/core/ent.d.ts +53 -105
- package/core/ent.js +104 -599
- package/core/global_schema.d.ts +7 -0
- package/core/global_schema.js +51 -0
- package/core/loaders/assoc_count_loader.d.ts +4 -2
- package/core/loaders/assoc_count_loader.js +10 -2
- package/core/loaders/assoc_edge_loader.d.ts +2 -3
- package/core/loaders/assoc_edge_loader.js +16 -7
- package/core/loaders/index.d.ts +0 -1
- package/core/loaders/index.js +1 -3
- package/core/loaders/loader.d.ts +3 -3
- package/core/loaders/loader.js +3 -20
- package/core/loaders/object_loader.d.ts +30 -10
- package/core/loaders/object_loader.js +179 -40
- package/core/loaders/query_loader.d.ts +4 -4
- package/core/loaders/query_loader.js +14 -19
- package/core/loaders/raw_count_loader.d.ts +1 -0
- package/core/loaders/raw_count_loader.js +3 -2
- package/core/privacy.d.ts +19 -10
- package/core/privacy.js +47 -26
- package/core/query/assoc_query.js +1 -1
- package/core/query/custom_clause_query.d.ts +6 -3
- package/core/query/custom_clause_query.js +36 -9
- package/core/query/custom_query.d.ts +3 -1
- package/core/query/custom_query.js +29 -6
- package/core/query/query.d.ts +12 -2
- package/core/query/query.js +67 -38
- package/core/query/shared_assoc_test.js +151 -10
- package/core/query/shared_test.d.ts +2 -2
- package/core/query/shared_test.js +90 -30
- package/core/query_impl.d.ts +8 -0
- package/core/query_impl.js +28 -0
- package/core/viewer.d.ts +2 -0
- package/core/viewer.js +2 -0
- package/graphql/graphql.d.ts +103 -19
- package/graphql/graphql.js +169 -134
- package/graphql/graphql_field_helpers.d.ts +9 -3
- package/graphql/graphql_field_helpers.js +22 -2
- package/graphql/index.d.ts +2 -1
- package/graphql/index.js +5 -2
- 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 +1 -1
- package/imports/index.js +2 -2
- package/index.d.ts +12 -1
- package/index.js +18 -6
- package/package.json +20 -17
- package/parse_schema/parse.d.ts +10 -4
- package/parse_schema/parse.js +70 -24
- package/schema/base_schema.d.ts +8 -0
- package/schema/base_schema.js +11 -0
- package/schema/field.d.ts +6 -3
- package/schema/field.js +72 -17
- package/schema/index.d.ts +1 -1
- package/schema/index.js +2 -1
- package/schema/json_field.d.ts +3 -3
- package/schema/json_field.js +4 -1
- package/schema/schema.d.ts +42 -5
- package/schema/schema.js +35 -41
- package/schema/struct_field.d.ts +8 -6
- package/schema/struct_field.js +67 -8
- package/schema/union_field.d.ts +1 -1
- package/scripts/custom_compiler.js +4 -4
- package/scripts/custom_graphql.js +105 -75
- package/scripts/move_types.js +4 -1
- package/scripts/read_schema.js +2 -2
- package/testutils/action/complex_schemas.d.ts +1 -1
- package/testutils/action/complex_schemas.js +10 -3
- package/testutils/builder.d.ts +3 -0
- package/testutils/builder.js +6 -0
- package/testutils/db/temp_db.d.ts +9 -1
- package/testutils/db/temp_db.js +82 -14
- package/testutils/db_mock.js +1 -3
- package/testutils/ent-graphql-tests/index.d.ts +1 -1
- package/testutils/ent-graphql-tests/index.js +30 -19
- package/testutils/fake_comms.js +1 -1
- package/testutils/fake_data/fake_contact.d.ts +1 -1
- package/testutils/fake_data/fake_tag.d.ts +1 -1
- package/testutils/fake_data/fake_user.d.ts +3 -3
- package/testutils/fake_data/fake_user.js +15 -4
- package/testutils/fake_data/tag_query.js +8 -3
- package/testutils/fake_data/test_helpers.d.ts +3 -2
- package/testutils/fake_data/test_helpers.js +4 -4
- package/testutils/fake_data/user_query.d.ts +5 -2
- package/testutils/fake_data/user_query.js +19 -2
- package/testutils/fake_log.js +1 -1
- package/tsc/ast.js +2 -1
- package/tsc/move_generated.js +2 -2
- package/tsc/transform.d.ts +2 -2
- package/tsc/transform.js +4 -3
- package/tsc/transform_ent.js +2 -1
- package/tsc/transform_schema.js +4 -3
- package/core/loaders/index_loader.d.ts +0 -14
- package/core/loaders/index_loader.js +0 -27
|
@@ -173,11 +173,14 @@ exports.ChangelogSchema = (0, builder_1.getBuilderSchemaFromFields)({
|
|
|
173
173
|
}, Changelog);
|
|
174
174
|
exports.MessageSchema = (0, builder_1.getBuilderSchemaFromFields)({
|
|
175
175
|
// TODO both id fields
|
|
176
|
-
sender: (0, field_1.StringType)(
|
|
176
|
+
sender: (0, field_1.StringType)({
|
|
177
|
+
index: true,
|
|
178
|
+
}),
|
|
177
179
|
recipient: (0, field_1.StringType)(),
|
|
178
180
|
message: (0, field_1.StringType)(),
|
|
179
181
|
transient: (0, field_1.BooleanType)({ nullable: true }),
|
|
180
182
|
expiresAt: (0, field_1.TimestampType)({ nullable: true }),
|
|
183
|
+
delivered: (0, field_1.BooleanType)({ defaultValueOnCreate: () => false }),
|
|
181
184
|
}, builder_1.Message);
|
|
182
185
|
jest.spyOn(action, "saveBuilder").mockImplementation(saveBuilder);
|
|
183
186
|
jest.spyOn(action, "saveBuilderX").mockImplementation(saveBuilderX);
|
|
@@ -233,8 +236,12 @@ class MessageAction extends builder_1.SimpleAction {
|
|
|
233
236
|
changeset: (builder, _input) => {
|
|
234
237
|
let sender = builder.fields.get("sender");
|
|
235
238
|
let recipient = builder.fields.get("recipient");
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
if (sender) {
|
|
240
|
+
builder.orchestrator.addInboundEdge(sender, "senderToMessage", "user");
|
|
241
|
+
}
|
|
242
|
+
if (recipient) {
|
|
243
|
+
builder.orchestrator.addInboundEdge(recipient, "recipientToMessage", "user");
|
|
244
|
+
}
|
|
238
245
|
},
|
|
239
246
|
},
|
|
240
247
|
];
|
package/testutils/builder.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { FieldMap, Schema } from "../schema";
|
|
|
5
5
|
import { SchemaConfig, EntSchema } from "../schema/base_schema";
|
|
6
6
|
import { FieldInfoMap } from "../schema/schema";
|
|
7
7
|
import { Clause } from "src/core/clause";
|
|
8
|
+
import { ChangesetOptions } from "../action/action";
|
|
8
9
|
export declare class BaseEnt {
|
|
9
10
|
viewer: Viewer;
|
|
10
11
|
readonly data: Data;
|
|
@@ -76,6 +77,7 @@ export declare class SimpleBuilder<T extends Ent, TExistingEnt extends TMaybleNu
|
|
|
76
77
|
storeData(k: string, v: any): void;
|
|
77
78
|
getStoredData(k: string): any;
|
|
78
79
|
build(): Promise<Changeset>;
|
|
80
|
+
buildWithOptions_BETA(options: ChangesetOptions): Promise<Changeset>;
|
|
79
81
|
editedEnt(): Promise<T | null>;
|
|
80
82
|
editedEntX(): Promise<T>;
|
|
81
83
|
save(): Promise<void>;
|
|
@@ -98,6 +100,7 @@ export declare class SimpleAction<T extends Ent, TExistingEnt extends TMaybleNul
|
|
|
98
100
|
getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
|
|
99
101
|
getInput(): Data;
|
|
100
102
|
changeset(): Promise<Changeset>;
|
|
103
|
+
changesetWithOptions_BETA(options: ChangesetOptions): Promise<Changeset>;
|
|
101
104
|
valid(): Promise<boolean>;
|
|
102
105
|
validX(): Promise<void>;
|
|
103
106
|
validWithErrors(): Promise<Error[]>;
|
package/testutils/builder.js
CHANGED
|
@@ -244,6 +244,9 @@ class SimpleBuilder {
|
|
|
244
244
|
build() {
|
|
245
245
|
return this.orchestrator.build();
|
|
246
246
|
}
|
|
247
|
+
buildWithOptions_BETA(options) {
|
|
248
|
+
return this.orchestrator.buildWithOptions_BETA(options);
|
|
249
|
+
}
|
|
247
250
|
async editedEnt() {
|
|
248
251
|
return await this.orchestrator.editedEnt();
|
|
249
252
|
}
|
|
@@ -292,6 +295,9 @@ class SimpleAction {
|
|
|
292
295
|
changeset() {
|
|
293
296
|
return this.builder.build();
|
|
294
297
|
}
|
|
298
|
+
changesetWithOptions_BETA(options) {
|
|
299
|
+
return this.builder.buildWithOptions_BETA(options);
|
|
300
|
+
}
|
|
295
301
|
valid() {
|
|
296
302
|
return this.builder.orchestrator.valid();
|
|
297
303
|
}
|
|
@@ -21,6 +21,7 @@ interface Column extends SchemaItem {
|
|
|
21
21
|
}
|
|
22
22
|
interface Constraint extends SchemaItem {
|
|
23
23
|
generate(): string;
|
|
24
|
+
postCreate?(): boolean;
|
|
24
25
|
}
|
|
25
26
|
interface Index extends SchemaItem {
|
|
26
27
|
generate(): string;
|
|
@@ -72,6 +73,11 @@ export declare function dateList(name: string, opts?: options): Column;
|
|
|
72
73
|
export declare function boolList(name: string, opts?: options): Column;
|
|
73
74
|
export declare function table(name: string, ...items: SchemaItem[]): Table;
|
|
74
75
|
export declare function enumType(name: string, values: string[]): CoreConcept;
|
|
76
|
+
interface TempDBOptions {
|
|
77
|
+
dialect: Dialect;
|
|
78
|
+
sqliteConnString?: string;
|
|
79
|
+
tables?: CoreConcept[] | (() => CoreConcept[]);
|
|
80
|
+
}
|
|
75
81
|
export declare class TempDB {
|
|
76
82
|
private db;
|
|
77
83
|
private client;
|
|
@@ -80,7 +86,9 @@ export declare class TempDB {
|
|
|
80
86
|
private dialect;
|
|
81
87
|
private sqlite;
|
|
82
88
|
private setTables;
|
|
89
|
+
private sqliteConnString;
|
|
83
90
|
constructor(dialect: Dialect, tables?: CoreConcept[] | (() => CoreConcept[]));
|
|
91
|
+
constructor(opts: TempDBOptions);
|
|
84
92
|
getDialect(): Dialect;
|
|
85
93
|
__getTables(): Map<string, CoreConcept>;
|
|
86
94
|
beforeAll(setupConnString?: boolean): Promise<void>;
|
|
@@ -94,7 +102,7 @@ export declare class TempDB {
|
|
|
94
102
|
create(...tables: CoreConcept[]): Promise<void>;
|
|
95
103
|
}
|
|
96
104
|
export declare function assoc_edge_config_table(): Table;
|
|
97
|
-
export declare function assoc_edge_table(name: string, global?: boolean): Table;
|
|
105
|
+
export declare function assoc_edge_table(name: string, global?: boolean, unique_edge?: boolean): Table;
|
|
98
106
|
interface setupOptions {
|
|
99
107
|
disableDeleteAfterEachTest?: boolean;
|
|
100
108
|
}
|
package/testutils/db/temp_db.js
CHANGED
|
@@ -64,6 +64,20 @@ function check(name, condition) {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
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
|
+
}
|
|
67
81
|
function isPostCreateIndex(s) {
|
|
68
82
|
return (s.postCreate !== undefined &&
|
|
69
83
|
s.postCreate());
|
|
@@ -367,8 +381,15 @@ function randomDB() {
|
|
|
367
381
|
class TempDB {
|
|
368
382
|
constructor(dialect, tables) {
|
|
369
383
|
this.tables = new Map();
|
|
370
|
-
|
|
371
|
-
|
|
384
|
+
if (typeof dialect === "string") {
|
|
385
|
+
this.dialect = dialect;
|
|
386
|
+
this.setTables = tables;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
this.dialect = dialect.dialect;
|
|
390
|
+
this.setTables = dialect.tables;
|
|
391
|
+
this.sqliteConnString = dialect.sqliteConnString;
|
|
392
|
+
}
|
|
372
393
|
}
|
|
373
394
|
getDialect() {
|
|
374
395
|
return this.dialect;
|
|
@@ -401,6 +422,10 @@ class TempDB {
|
|
|
401
422
|
}
|
|
402
423
|
db_1.default.initDB({
|
|
403
424
|
connectionString: connStr,
|
|
425
|
+
cfg: {
|
|
426
|
+
max: 100,
|
|
427
|
+
idleTimeoutMillis: 100,
|
|
428
|
+
},
|
|
404
429
|
});
|
|
405
430
|
}
|
|
406
431
|
else {
|
|
@@ -416,10 +441,17 @@ class TempDB {
|
|
|
416
441
|
await this.dbClient.connect();
|
|
417
442
|
}
|
|
418
443
|
else {
|
|
419
|
-
|
|
420
|
-
|
|
444
|
+
let connString;
|
|
445
|
+
if (this.sqliteConnString) {
|
|
446
|
+
connString = this.sqliteConnString;
|
|
421
447
|
}
|
|
422
|
-
|
|
448
|
+
else {
|
|
449
|
+
if (process.env.DB_CONNECTION_STRING === undefined) {
|
|
450
|
+
throw new Error(`DB_CONNECTION_STRING required for sqlite if sqliteConnString is not set`);
|
|
451
|
+
}
|
|
452
|
+
connString = process.env.DB_CONNECTION_STRING;
|
|
453
|
+
}
|
|
454
|
+
const filePath = connString.substr(10);
|
|
423
455
|
this.sqlite = (0, better_sqlite3_1.default)(filePath);
|
|
424
456
|
}
|
|
425
457
|
if (this.setTables) {
|
|
@@ -463,6 +495,16 @@ class TempDB {
|
|
|
463
495
|
async afterAll() {
|
|
464
496
|
if (this.dialect === db_1.Dialect.SQLite) {
|
|
465
497
|
this.sqlite.close();
|
|
498
|
+
if (!this.sqlite.memory) {
|
|
499
|
+
const f = this.getSqliteClient().name;
|
|
500
|
+
fs.rmSync(f);
|
|
501
|
+
fs.rmSync(`${f}-shm`, {
|
|
502
|
+
force: true,
|
|
503
|
+
});
|
|
504
|
+
fs.rmSync(`${f}-wal`, {
|
|
505
|
+
force: true,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
466
508
|
return;
|
|
467
509
|
}
|
|
468
510
|
// end our connection to db
|
|
@@ -471,6 +513,7 @@ class TempDB {
|
|
|
471
513
|
await db_1.default.getInstance().endPool();
|
|
472
514
|
// drop db
|
|
473
515
|
await this.client.query(`DROP DATABASE ${this.db}`);
|
|
516
|
+
// console.log(this.db);
|
|
474
517
|
await this.client.end();
|
|
475
518
|
}
|
|
476
519
|
getDB() {
|
|
@@ -515,10 +558,22 @@ function assoc_edge_config_table() {
|
|
|
515
558
|
exports.assoc_edge_config_table = assoc_edge_config_table;
|
|
516
559
|
// if global flag is true, add any column from testEdgeGlobalSchema
|
|
517
560
|
// up to caller to set/clear that as needed
|
|
518
|
-
function assoc_edge_table(name, global) {
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
561
|
+
function assoc_edge_table(name, global, unique_edge) {
|
|
562
|
+
const items = [
|
|
563
|
+
uuid("id1"),
|
|
564
|
+
text("id1_type"),
|
|
565
|
+
// same as in assoc_edge_config_table
|
|
566
|
+
text("edge_type"),
|
|
567
|
+
uuid("id2"),
|
|
568
|
+
text("id2_type"),
|
|
569
|
+
timestamptz("time"),
|
|
570
|
+
text("data", { nullable: true }),
|
|
571
|
+
primaryKey(`${name}_pkey`, ["id1", "id2", "edge_type"]),
|
|
572
|
+
];
|
|
573
|
+
if (unique_edge) {
|
|
574
|
+
items.push(unique(`${name}_unique_id1_edge_type`, ["id1", "edge_type"], name));
|
|
575
|
+
}
|
|
576
|
+
const t = table(name, ...items);
|
|
522
577
|
if (global) {
|
|
523
578
|
for (const k in test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields) {
|
|
524
579
|
const col = getColumnFromField(k, test_edge_global_schema_1.testEdgeGlobalSchema.extraEdgeFields[k], db_1.Dialect.Postgres);
|
|
@@ -529,10 +584,15 @@ function assoc_edge_table(name, global) {
|
|
|
529
584
|
}
|
|
530
585
|
exports.assoc_edge_table = assoc_edge_table;
|
|
531
586
|
function setupSqlite(connString, tables, opts) {
|
|
532
|
-
let tdb = new TempDB(
|
|
587
|
+
let tdb = new TempDB({
|
|
588
|
+
dialect: db_1.Dialect.SQLite,
|
|
589
|
+
tables,
|
|
590
|
+
sqliteConnString: connString,
|
|
591
|
+
});
|
|
533
592
|
beforeAll(async () => {
|
|
534
|
-
|
|
535
|
-
|
|
593
|
+
(0, config_1.loadConfig)({
|
|
594
|
+
dbConnectionString: connString,
|
|
595
|
+
});
|
|
536
596
|
await tdb.beforeAll();
|
|
537
597
|
const conn = db_1.default.getInstance().getConnection();
|
|
538
598
|
expect(conn.db.memory).toBe(false);
|
|
@@ -554,7 +614,6 @@ function setupSqlite(connString, tables, opts) {
|
|
|
554
614
|
}
|
|
555
615
|
afterAll(async () => {
|
|
556
616
|
await tdb.afterAll();
|
|
557
|
-
fs.rmSync(tdb.getSqliteClient().name);
|
|
558
617
|
delete process.env.DB_CONNECTION_STRING;
|
|
559
618
|
});
|
|
560
619
|
return tdb;
|
|
@@ -601,6 +660,7 @@ function getSchemaTable(schema, dialect) {
|
|
|
601
660
|
for (const [fieldName, field] of fields) {
|
|
602
661
|
items.push(getColumnFromField(fieldName, field, dialect));
|
|
603
662
|
}
|
|
663
|
+
const tableName = (0, builder_1.getTableName)(schema);
|
|
604
664
|
if (schema.constraints) {
|
|
605
665
|
for (const constraint of schema.constraints) {
|
|
606
666
|
switch (constraint.type) {
|
|
@@ -622,10 +682,15 @@ function getSchemaTable(schema, dialect) {
|
|
|
622
682
|
}
|
|
623
683
|
items.push(check(constraint.name, constraint.condition));
|
|
624
684
|
break;
|
|
685
|
+
case schema_1.ConstraintType.Unique:
|
|
686
|
+
items.push(unique(constraint.name, constraint.columns, tableName));
|
|
687
|
+
break;
|
|
688
|
+
default:
|
|
689
|
+
throw new Error(`unknown constraint type ${constraint.type}`);
|
|
625
690
|
}
|
|
626
691
|
}
|
|
627
692
|
}
|
|
628
|
-
return table(
|
|
693
|
+
return table(tableName, ...items);
|
|
629
694
|
}
|
|
630
695
|
exports.getSchemaTable = getSchemaTable;
|
|
631
696
|
function getColumnForDbType(t, dialect) {
|
|
@@ -702,6 +767,9 @@ function buildOpts(f) {
|
|
|
702
767
|
if (f.serverDefault) {
|
|
703
768
|
ret.default = f.serverDefault;
|
|
704
769
|
}
|
|
770
|
+
if (f.unique) {
|
|
771
|
+
ret.unique = true;
|
|
772
|
+
}
|
|
705
773
|
return ret;
|
|
706
774
|
}
|
|
707
775
|
function storageKey(fieldName, f) {
|
package/testutils/db_mock.js
CHANGED
|
@@ -263,10 +263,8 @@ class QueryRecorder {
|
|
|
263
263
|
});
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
-
exports.QueryRecorder = QueryRecorder;
|
|
267
266
|
QueryRecorder.queries = [];
|
|
268
267
|
QueryRecorder.ids = [];
|
|
269
268
|
// we need pkeys when storing...
|
|
270
269
|
QueryRecorder.data = new Map();
|
|
271
|
-
|
|
272
|
-
process.env.DB_CONNECTION_STRING = "INVALID DATABASE";
|
|
270
|
+
exports.QueryRecorder = QueryRecorder;
|
|
@@ -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 type Option = [string, any];
|
|
5
|
+
export type Option = [string, any] | [string, any, string];
|
|
6
6
|
interface queryConfig {
|
|
7
7
|
viewer?: Viewer;
|
|
8
8
|
init?: (app: Express) => void;
|
|
@@ -162,8 +162,9 @@ function makeGraphQLRequest(config, query, fieldArgs) {
|
|
|
162
162
|
}
|
|
163
163
|
function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
164
164
|
let fields;
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
const [typ] = getInnerType(fieldType, false);
|
|
166
|
+
if (typ instanceof graphql_1.GraphQLObjectType) {
|
|
167
|
+
fields = typ.getFields();
|
|
167
168
|
}
|
|
168
169
|
let topLevelTree = {};
|
|
169
170
|
options.forEach((option) => {
|
|
@@ -201,10 +202,11 @@ function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
|
201
202
|
}
|
|
202
203
|
// TODO this needs to be aware of paths etc so this part works for complicated
|
|
203
204
|
// cases but inlineFragmentRoot is a workaround for now.
|
|
204
|
-
function handleSubtree(obj, tree) {
|
|
205
|
+
function handleSubtree(obj, tree, parts) {
|
|
206
|
+
let parts2 = [...parts];
|
|
205
207
|
if (Array.isArray(obj)) {
|
|
206
208
|
for (const obj2 of obj) {
|
|
207
|
-
handleSubtree(obj2, tree);
|
|
209
|
+
handleSubtree(obj2, tree, parts2);
|
|
208
210
|
}
|
|
209
211
|
return;
|
|
210
212
|
}
|
|
@@ -213,28 +215,36 @@ function buildTreeFromQueryPaths(schema, fieldType, ...options) {
|
|
|
213
215
|
tree[key] = {};
|
|
214
216
|
}
|
|
215
217
|
if (typeof obj[key] === "object") {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
let parts2 = [...parts, key];
|
|
219
|
+
if (!scalarFieldAtLeaf(parts2)) {
|
|
220
|
+
handleSubtree(obj[key], tree[key], parts2);
|
|
218
221
|
}
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
224
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (!subField) {
|
|
225
|
+
function scalarFieldAtLeaf(pathFromRoot) {
|
|
226
|
+
let root = fields;
|
|
227
|
+
if (!root) {
|
|
226
228
|
return false;
|
|
227
229
|
}
|
|
228
|
-
|
|
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) {
|
|
229
241
|
return false;
|
|
230
242
|
}
|
|
231
|
-
|
|
232
|
-
const [typ, _] = getInnerType(subField.type, true);
|
|
233
|
-
return (0, graphql_1.isScalarType)(typ) || (0, graphql_1.isEnumType)(typ);
|
|
243
|
+
return (0, graphql_1.isScalarType)(subField) || (0, graphql_1.isEnumType)(subField);
|
|
234
244
|
}
|
|
235
245
|
if (i === parts.length - 1 && typeof option[1] === "object") {
|
|
236
|
-
if (!
|
|
237
|
-
handleSubtree(option[1], tree);
|
|
246
|
+
if (!scalarFieldAtLeaf(parts)) {
|
|
247
|
+
handleSubtree(option[1], tree, parts);
|
|
238
248
|
}
|
|
239
249
|
}
|
|
240
250
|
}
|
|
@@ -408,8 +418,9 @@ async function expectFromRoot(config, ...options) {
|
|
|
408
418
|
}
|
|
409
419
|
}
|
|
410
420
|
await Promise.all(options.map(async (option) => {
|
|
411
|
-
|
|
412
|
-
|
|
421
|
+
const path = option[0];
|
|
422
|
+
const expected = option[1];
|
|
423
|
+
const alias = option[2];
|
|
413
424
|
let nullPath;
|
|
414
425
|
let nullParts = [];
|
|
415
426
|
let undefinedPath;
|
|
@@ -432,7 +443,7 @@ async function expectFromRoot(config, ...options) {
|
|
|
432
443
|
}
|
|
433
444
|
}
|
|
434
445
|
}
|
|
435
|
-
let parts = splitPath(path);
|
|
446
|
+
let parts = splitPath(alias ?? path);
|
|
436
447
|
let current = result;
|
|
437
448
|
// possible to make this smarter and better
|
|
438
449
|
// e.g. when building up the tree above
|
package/testutils/fake_comms.js
CHANGED
|
@@ -34,4 +34,4 @@ export interface ContactCreateInput {
|
|
|
34
34
|
}
|
|
35
35
|
export declare function getContactBuilder(viewer: Viewer, input: ContactCreateInput): SimpleBuilder<FakeContact, null>;
|
|
36
36
|
export declare function createContact(viewer: Viewer, input: ContactCreateInput): Promise<void>;
|
|
37
|
-
export declare const contactLoader: ObjectLoaderFactory<
|
|
37
|
+
export declare const contactLoader: ObjectLoaderFactory<Data>;
|
|
@@ -33,4 +33,4 @@ export type TagEditInput = Partial<TagCreateInput>;
|
|
|
33
33
|
export declare function getTagBuilder(viewer: Viewer, input: TagCreateInput): import("../builder").SimpleBuilder<FakeTag, null>;
|
|
34
34
|
export declare function getTagAction(viewer: Viewer, input: TagCreateInput): SimpleAction<FakeTag, null>;
|
|
35
35
|
export declare function createTag(viewer: Viewer, input: TagCreateInput): Promise<FakeTag>;
|
|
36
|
-
export declare const tagLoader: ObjectLoaderFactory<
|
|
36
|
+
export declare const tagLoader: ObjectLoaderFactory<Data>;
|
|
@@ -46,7 +46,7 @@ export type UserEditInput = Partial<UserCreateInput>;
|
|
|
46
46
|
export declare function getUserBuilder(viewer: Viewer, input: UserCreateInput): import("../builder").SimpleBuilder<FakeUser, null>;
|
|
47
47
|
export declare function getUserAction(viewer: Viewer, input: UserCreateInput): SimpleAction<FakeUser, null>;
|
|
48
48
|
export declare function createUser(viewer: Viewer, input: UserCreateInput): Promise<FakeUser>;
|
|
49
|
-
export declare const userLoader: ObjectLoaderFactory<
|
|
50
|
-
export declare const userEmailLoader: ObjectLoaderFactory<
|
|
51
|
-
export declare const userPhoneNumberLoader: ObjectLoaderFactory<
|
|
49
|
+
export declare const userLoader: ObjectLoaderFactory<Data>;
|
|
50
|
+
export declare const userEmailLoader: ObjectLoaderFactory<Data>;
|
|
51
|
+
export declare const userPhoneNumberLoader: ObjectLoaderFactory<Data>;
|
|
52
52
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.userPhoneNumberLoader = exports.userEmailLoader = exports.userLoader = exports.createUser = exports.getUserAction = exports.getUserBuilder = exports.FakeUserSchema = exports.FakeUser = exports.ViewerWithAccessToken = void 0;
|
|
4
|
+
const base_1 = require("../../core/base");
|
|
4
5
|
const ent_1 = require("../../core/ent");
|
|
5
6
|
const privacy_1 = require("../../core/privacy");
|
|
6
7
|
const builder_1 = require("../builder");
|
|
@@ -28,9 +29,17 @@ class FakeUser {
|
|
|
28
29
|
return {
|
|
29
30
|
rules: [
|
|
30
31
|
privacy_1.AllowIfViewerRule,
|
|
31
|
-
|
|
32
|
+
{
|
|
33
|
+
async apply(v, ent) {
|
|
34
|
+
if (!(v instanceof ViewerWithAccessToken)) {
|
|
35
|
+
return (0, base_1.Skip)();
|
|
36
|
+
}
|
|
37
|
+
return v.hasToken("always_allow_user") ? (0, base_1.Allow)() : (0, base_1.Skip)();
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
// can view user if friends
|
|
32
41
|
new privacy_1.AllowIfViewerInboundEdgeExistsRule(internal_1.EdgeType.UserToFriends),
|
|
33
|
-
//can view user if following
|
|
42
|
+
// can view user if following
|
|
34
43
|
new privacy_1.AllowIfViewerInboundEdgeExistsRule(internal_1.EdgeType.UserToFollowing),
|
|
35
44
|
new privacy_1.AllowIfConditionAppliesRule((viewer, ent) => {
|
|
36
45
|
if (!(viewer instanceof ViewerWithAccessToken)) {
|
|
@@ -113,9 +122,11 @@ function getUserAction(viewer, input) {
|
|
|
113
122
|
m.set(key, input[key]);
|
|
114
123
|
}
|
|
115
124
|
const action = new builder_1.SimpleAction(viewer, exports.FakeUserSchema, m, action_1.WriteOperation.Insert, null);
|
|
116
|
-
action.viewerForEntLoad = (data) => {
|
|
125
|
+
action.viewerForEntLoad = (data, context) => {
|
|
117
126
|
// load the created ent using a VC of the newly created user.
|
|
118
|
-
return new viewer_1.IDViewer(data.id
|
|
127
|
+
return new viewer_1.IDViewer(data.id, {
|
|
128
|
+
context,
|
|
129
|
+
});
|
|
119
130
|
};
|
|
120
131
|
return action;
|
|
121
132
|
}
|
|
@@ -11,7 +11,7 @@ class UserToTagsFkeyQuery extends custom_query_1.CustomEdgeQueryBase {
|
|
|
11
11
|
groupCol: "owner_id",
|
|
12
12
|
name: "user_to_tags",
|
|
13
13
|
sortColumn: "canonical_name",
|
|
14
|
-
|
|
14
|
+
primarySortColIsUnique: true,
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
static query(viewer, src) {
|
|
@@ -29,8 +29,13 @@ class UserToTagsFkeyQueryAsc extends custom_query_1.CustomEdgeQueryBase {
|
|
|
29
29
|
loadEntOptions: internal_1.FakeTag.loaderOptions(),
|
|
30
30
|
groupCol: "owner_id",
|
|
31
31
|
name: "user_to_tags_asc",
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
orderby: [
|
|
33
|
+
{
|
|
34
|
+
column: "canonical_name",
|
|
35
|
+
direction: "ASC",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
primarySortColIsUnique: true,
|
|
34
39
|
});
|
|
35
40
|
}
|
|
36
41
|
static query(viewer, src) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Data, Ent } from "../../core/base";
|
|
1
|
+
import { Context, Data, Ent } from "../../core/base";
|
|
2
2
|
import { AssocEdge } from "../../core/ent";
|
|
3
3
|
import { TempDB } from "../db/temp_db";
|
|
4
4
|
import { FakeUser, UserCreateInput, ContactCreateInput, FakeContact } from ".";
|
|
@@ -7,13 +7,14 @@ import { BuilderSchema } from "../builder";
|
|
|
7
7
|
export declare function getContactInput(user: FakeUser, input?: Partial<ContactCreateInput>): ContactCreateInput;
|
|
8
8
|
export declare function getUserInput(input?: Partial<UserCreateInput>): UserCreateInput;
|
|
9
9
|
export declare function getEventInput(user: FakeUser, input?: Partial<EventCreateInput>): EventCreateInput;
|
|
10
|
-
export declare function createTestUser(input?: Partial<UserCreateInput
|
|
10
|
+
export declare function createTestUser(input?: Partial<UserCreateInput>, ctx?: Context): Promise<FakeUser>;
|
|
11
11
|
export declare const inputs: Partial<ContactCreateInput>[];
|
|
12
12
|
interface createContactOptions {
|
|
13
13
|
input?: Partial<UserCreateInput>;
|
|
14
14
|
slice?: number;
|
|
15
15
|
user?: FakeUser;
|
|
16
16
|
start?: number;
|
|
17
|
+
ctx?: Context;
|
|
17
18
|
}
|
|
18
19
|
export declare function createAllContacts(opts?: createContactOptions): Promise<[FakeUser, FakeContact[]]>;
|
|
19
20
|
export declare function createUserPlusFriendRequests(input?: Partial<UserCreateInput>, slice?: number): Promise<[FakeUser, FakeUser[]]>;
|
|
@@ -53,8 +53,8 @@ function getEventInput(user, input) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
exports.getEventInput = getEventInput;
|
|
56
|
-
async function createTestUser(input) {
|
|
57
|
-
const user = await (0, _1.createUser)(new viewer_1.LoggedOutViewer(), {
|
|
56
|
+
async function createTestUser(input, ctx) {
|
|
57
|
+
const user = await (0, _1.createUser)(new viewer_1.LoggedOutViewer(ctx), {
|
|
58
58
|
firstName: "Jon",
|
|
59
59
|
lastName: "Snow",
|
|
60
60
|
password: "12345678",
|
|
@@ -93,7 +93,7 @@ exports.inputs = [
|
|
|
93
93
|
async function createAllContacts(opts) {
|
|
94
94
|
let { input, slice, user } = opts || {};
|
|
95
95
|
if (!user) {
|
|
96
|
-
user = await createTestUser(input);
|
|
96
|
+
user = await createTestUser(input, opts?.ctx);
|
|
97
97
|
}
|
|
98
98
|
const userr = user;
|
|
99
99
|
if (opts?.start) {
|
|
@@ -257,7 +257,7 @@ async function createAllEvents(opts) {
|
|
|
257
257
|
const input = opts.eventInputs?.[idx];
|
|
258
258
|
const builder = (0, fake_event_1.getEventBuilder)(user.viewer, getEventInput(user, input));
|
|
259
259
|
await builder.saveX();
|
|
260
|
-
return
|
|
260
|
+
return builder.editedEntX();
|
|
261
261
|
}));
|
|
262
262
|
expect(events.length).toBe(opts.howMany);
|
|
263
263
|
return [user, events];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ent, ID, Viewer } from "../../core/base";
|
|
1
|
+
import { Data, Ent, ID, Viewer } from "../../core/base";
|
|
2
2
|
import { CustomEdgeQueryBase } from "../../core/query/custom_query";
|
|
3
3
|
import { AssocEdge } from "../../core/ent";
|
|
4
4
|
import * as clause from "../../core/clause";
|
|
@@ -39,6 +39,8 @@ export declare class UserToFriendsQuery extends AssocEdgeQueryBase<FakeUser, Fak
|
|
|
39
39
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
40
40
|
}
|
|
41
41
|
export declare class CustomEdge extends AssocEdge {
|
|
42
|
+
deleted_at: Date | null;
|
|
43
|
+
constructor(data: Data);
|
|
42
44
|
loadUser(viewer: Viewer): Promise<FakeUser | null>;
|
|
43
45
|
}
|
|
44
46
|
export declare class UserToCustomEdgeQuery extends AssocEdgeQueryBase<FakeUser, FakeUser, CustomEdge> {
|
|
@@ -60,7 +62,7 @@ export declare class UserToFriendRequestsQuery extends AssocEdgeQueryBase<FakeUs
|
|
|
60
62
|
queryEventsAttending(): UserToEventsAttendingQuery;
|
|
61
63
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
62
64
|
}
|
|
63
|
-
export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBase<FakeUser, FakeUser,
|
|
65
|
+
export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBase<FakeUser, FakeUser, CustomEdge> {
|
|
64
66
|
constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeUser>);
|
|
65
67
|
getPrivacyPolicy(): import("../../core/base").PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
|
|
66
68
|
sourceEnt(id: ID): Promise<FakeUser | null>;
|
|
@@ -70,6 +72,7 @@ export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBas
|
|
|
70
72
|
queryHostedEvents(): UserToHostedEventsQuery;
|
|
71
73
|
queryEventsAttending(): UserToEventsAttendingQuery;
|
|
72
74
|
queryCustomEdge(): UserToCustomEdgeQuery;
|
|
75
|
+
withoutTransformations(): this;
|
|
73
76
|
}
|
|
74
77
|
export declare class UserToEventsAttendingQuery extends AssocEdgeQueryBase<FakeUser, FakeEvent, AssocEdge> {
|
|
75
78
|
constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeEvent>);
|
|
@@ -107,7 +107,12 @@ class UserToContactsFkeyQueryAsc extends custom_query_1.CustomEdgeQueryBase {
|
|
|
107
107
|
loadEntOptions: internal_1.FakeContact.loaderOptions(),
|
|
108
108
|
groupCol: "user_id",
|
|
109
109
|
name: "user_to_contacts",
|
|
110
|
-
|
|
110
|
+
orderby: [
|
|
111
|
+
{
|
|
112
|
+
column: "created_at",
|
|
113
|
+
direction: "ASC",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
111
116
|
});
|
|
112
117
|
}
|
|
113
118
|
static query(viewer, src) {
|
|
@@ -147,6 +152,11 @@ class UserToFriendsQuery extends assoc_query_1.AssocEdgeQueryBase {
|
|
|
147
152
|
exports.UserToFriendsQuery = UserToFriendsQuery;
|
|
148
153
|
// example with custom method
|
|
149
154
|
class CustomEdge extends ent_1.AssocEdge {
|
|
155
|
+
constructor(data) {
|
|
156
|
+
super(data);
|
|
157
|
+
this.deleted_at = null;
|
|
158
|
+
this.deleted_at = data.deleted_at;
|
|
159
|
+
}
|
|
150
160
|
async loadUser(viewer) {
|
|
151
161
|
return await internal_1.FakeUser.load(viewer, this.id2);
|
|
152
162
|
}
|
|
@@ -205,7 +215,7 @@ class UserToFriendRequestsQuery extends assoc_query_1.AssocEdgeQueryBase {
|
|
|
205
215
|
exports.UserToFriendRequestsQuery = UserToFriendRequestsQuery;
|
|
206
216
|
class UserToIncomingFriendRequestsQuery extends assoc_query_1.AssocEdgeQueryBase {
|
|
207
217
|
constructor(viewer, src) {
|
|
208
|
-
super(viewer, src, new assoc_count_loader_1.AssocEdgeCountLoaderFactory(internal_1.EdgeType.UserToIncomingFriendRequests), new assoc_edge_loader_1.AssocEdgeLoaderFactory(internal_1.EdgeType.UserToIncomingFriendRequests,
|
|
218
|
+
super(viewer, src, new assoc_count_loader_1.AssocEdgeCountLoaderFactory(internal_1.EdgeType.UserToIncomingFriendRequests), new assoc_edge_loader_1.AssocEdgeLoaderFactory(internal_1.EdgeType.UserToIncomingFriendRequests, CustomEdge), internal_1.FakeUser.loaderOptions());
|
|
209
219
|
}
|
|
210
220
|
getPrivacyPolicy() {
|
|
211
221
|
return privacy_1.AllowIfViewerPrivacyPolicy;
|
|
@@ -231,6 +241,13 @@ class UserToIncomingFriendRequestsQuery extends assoc_query_1.AssocEdgeQueryBase
|
|
|
231
241
|
queryCustomEdge() {
|
|
232
242
|
return UserToCustomEdgeQuery.query(this.viewer, this);
|
|
233
243
|
}
|
|
244
|
+
// this is generated in codegen. we'll just add it manually here
|
|
245
|
+
withoutTransformations() {
|
|
246
|
+
this.configureEdgeQueryableDataOptions({
|
|
247
|
+
disableTransformations: true,
|
|
248
|
+
});
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
234
251
|
}
|
|
235
252
|
exports.UserToIncomingFriendRequestsQuery = UserToIncomingFriendRequestsQuery;
|
|
236
253
|
class UserToEventsAttendingQuery extends assoc_query_1.AssocEdgeQueryBase {
|