@snowtop/ent 0.1.0-alpha160-test7 → 0.1.0-alpha160
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/core/query/shared_assoc_test.d.ts +2 -0
- package/core/query/shared_assoc_test.js +804 -0
- package/core/query/shared_test.d.ts +21 -0
- package/core/query/shared_test.js +736 -0
- package/graphql/query/shared_assoc_test.d.ts +1 -0
- package/graphql/query/shared_assoc_test.js +203 -0
- package/package.json +8 -53
- package/dist/package.json +0 -64
- package/src/action/action.ts +0 -330
- package/src/action/executor.ts +0 -453
- package/src/action/experimental_action.ts +0 -277
- package/src/action/index.ts +0 -31
- package/src/action/operations.ts +0 -967
- package/src/action/orchestrator.ts +0 -1527
- package/src/action/privacy.ts +0 -37
- package/src/action/relative_value.ts +0 -242
- package/src/action/transaction.ts +0 -38
- package/src/auth/auth.ts +0 -77
- package/src/auth/index.ts +0 -8
- package/src/core/base.ts +0 -367
- package/src/core/clause.ts +0 -1065
- package/src/core/config.ts +0 -219
- package/src/core/const.ts +0 -5
- package/src/core/context.ts +0 -135
- package/src/core/convert.ts +0 -106
- package/src/core/date.ts +0 -23
- package/src/core/db.ts +0 -498
- package/src/core/ent.ts +0 -1740
- package/src/core/global_schema.ts +0 -49
- package/src/core/loaders/assoc_count_loader.ts +0 -99
- package/src/core/loaders/assoc_edge_loader.ts +0 -250
- package/src/core/loaders/index.ts +0 -12
- package/src/core/loaders/loader.ts +0 -66
- package/src/core/loaders/object_loader.ts +0 -489
- package/src/core/loaders/query_loader.ts +0 -314
- package/src/core/loaders/raw_count_loader.ts +0 -175
- package/src/core/logger.ts +0 -49
- package/src/core/privacy.ts +0 -660
- package/src/core/query/assoc_query.ts +0 -240
- package/src/core/query/custom_clause_query.ts +0 -174
- package/src/core/query/custom_query.ts +0 -302
- package/src/core/query/index.ts +0 -9
- package/src/core/query/query.ts +0 -674
- package/src/core/query_impl.ts +0 -32
- package/src/core/viewer.ts +0 -52
- package/src/ent.code-workspace +0 -73
- package/src/graphql/builtins/connection.ts +0 -25
- package/src/graphql/builtins/edge.ts +0 -16
- package/src/graphql/builtins/node.ts +0 -12
- package/src/graphql/graphql.ts +0 -891
- package/src/graphql/graphql_field_helpers.ts +0 -221
- package/src/graphql/index.ts +0 -42
- package/src/graphql/mutations/union.ts +0 -39
- package/src/graphql/node_resolver.ts +0 -122
- package/src/graphql/query/connection_type.ts +0 -113
- package/src/graphql/query/edge_connection.ts +0 -171
- package/src/graphql/query/page_info.ts +0 -34
- package/src/graphql/query/shared_edge_connection.ts +0 -287
- package/src/graphql/scalars/orderby_direction.ts +0 -13
- package/src/graphql/scalars/time.ts +0 -38
- package/src/imports/dataz/example1/_auth.ts +0 -51
- package/src/imports/dataz/example1/_viewer.ts +0 -35
- package/src/imports/index.ts +0 -213
- package/src/index.ts +0 -145
- package/src/parse_schema/parse.ts +0 -585
- package/src/schema/base_schema.ts +0 -224
- package/src/schema/field.ts +0 -1087
- package/src/schema/index.ts +0 -53
- package/src/schema/json_field.ts +0 -94
- package/src/schema/schema.ts +0 -1028
- package/src/schema/struct_field.ts +0 -234
- package/src/schema/union_field.ts +0 -105
- package/src/scripts/custom_compiler.ts +0 -331
- package/src/scripts/custom_graphql.ts +0 -550
- package/src/scripts/migrate_v0.1.ts +0 -41
- package/src/scripts/move_types.ts +0 -131
- package/src/scripts/read_schema.ts +0 -67
- package/src/setupPackage.js +0 -42
- package/src/testutils/action/complex_schemas.ts +0 -517
- package/src/testutils/builder.ts +0 -422
- package/src/testutils/context/test_context.ts +0 -25
- package/src/testutils/db/fixture.ts +0 -32
- package/src/testutils/db/temp_db.ts +0 -941
- package/src/testutils/db/value.ts +0 -294
- package/src/testutils/db_mock.ts +0 -351
- package/src/testutils/db_time_zone.ts +0 -40
- package/src/testutils/ent-graphql-tests/index.ts +0 -653
- package/src/testutils/fake_comms.ts +0 -50
- package/src/testutils/fake_data/const.ts +0 -64
- package/src/testutils/fake_data/events_query.ts +0 -145
- package/src/testutils/fake_data/fake_contact.ts +0 -150
- package/src/testutils/fake_data/fake_event.ts +0 -150
- package/src/testutils/fake_data/fake_tag.ts +0 -139
- package/src/testutils/fake_data/fake_user.ts +0 -232
- package/src/testutils/fake_data/index.ts +0 -1
- package/src/testutils/fake_data/internal.ts +0 -8
- package/src/testutils/fake_data/tag_query.ts +0 -56
- package/src/testutils/fake_data/test_helpers.ts +0 -388
- package/src/testutils/fake_data/user_query.ts +0 -524
- package/src/testutils/fake_log.ts +0 -52
- package/src/testutils/mock_date.ts +0 -10
- package/src/testutils/mock_log.ts +0 -39
- package/src/testutils/parse_sql.ts +0 -685
- package/src/testutils/test_edge_global_schema.ts +0 -49
- package/src/testutils/write.ts +0 -70
- package/src/tsc/ast.ts +0 -351
- package/src/tsc/compilerOptions.ts +0 -85
- package/src/tsc/move_generated.ts +0 -191
- package/src/tsc/transform.ts +0 -226
- package/src/tsc/transform_action.ts +0 -224
- package/src/tsc/transform_ent.ts +0 -66
- package/src/tsc/transform_schema.ts +0 -546
- package/tsconfig.json +0 -20
- /package/{dist/action → action}/action.d.ts +0 -0
- /package/{dist/action → action}/action.js +0 -0
- /package/{dist/action → action}/executor.d.ts +0 -0
- /package/{dist/action → action}/executor.js +0 -0
- /package/{dist/action → action}/experimental_action.d.ts +0 -0
- /package/{dist/action → action}/experimental_action.js +0 -0
- /package/{dist/action → action}/index.d.ts +0 -0
- /package/{dist/action → action}/index.js +0 -0
- /package/{dist/action → action}/operations.d.ts +0 -0
- /package/{dist/action → action}/operations.js +0 -0
- /package/{dist/action → action}/orchestrator.d.ts +0 -0
- /package/{dist/action → action}/orchestrator.js +0 -0
- /package/{dist/action → action}/privacy.d.ts +0 -0
- /package/{dist/action → action}/privacy.js +0 -0
- /package/{dist/action → action}/relative_value.d.ts +0 -0
- /package/{dist/action → action}/relative_value.js +0 -0
- /package/{dist/action → action}/transaction.d.ts +0 -0
- /package/{dist/action → action}/transaction.js +0 -0
- /package/{dist/auth → auth}/auth.d.ts +0 -0
- /package/{dist/auth → auth}/auth.js +0 -0
- /package/{dist/auth → auth}/index.d.ts +0 -0
- /package/{dist/auth → auth}/index.js +0 -0
- /package/{dist/core → core}/base.d.ts +0 -0
- /package/{dist/core → core}/base.js +0 -0
- /package/{dist/core → core}/clause.d.ts +0 -0
- /package/{dist/core → core}/clause.js +0 -0
- /package/{dist/core → core}/config.d.ts +0 -0
- /package/{dist/core → core}/config.js +0 -0
- /package/{dist/core → core}/const.d.ts +0 -0
- /package/{dist/core → core}/const.js +0 -0
- /package/{dist/core → core}/context.d.ts +0 -0
- /package/{dist/core → core}/context.js +0 -0
- /package/{dist/core → core}/convert.d.ts +0 -0
- /package/{dist/core → core}/convert.js +0 -0
- /package/{dist/core → core}/date.d.ts +0 -0
- /package/{dist/core → core}/date.js +0 -0
- /package/{dist/core → core}/db.d.ts +0 -0
- /package/{dist/core → core}/db.js +0 -0
- /package/{dist/core → core}/ent.d.ts +0 -0
- /package/{dist/core → core}/ent.js +0 -0
- /package/{dist/core → core}/global_schema.d.ts +0 -0
- /package/{dist/core → core}/global_schema.js +0 -0
- /package/{dist/core → core}/loaders/assoc_count_loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/assoc_count_loader.js +0 -0
- /package/{dist/core → core}/loaders/assoc_edge_loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/assoc_edge_loader.js +0 -0
- /package/{dist/core → core}/loaders/index.d.ts +0 -0
- /package/{dist/core → core}/loaders/index.js +0 -0
- /package/{dist/core → core}/loaders/loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/loader.js +0 -0
- /package/{dist/core → core}/loaders/object_loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/object_loader.js +0 -0
- /package/{dist/core → core}/loaders/query_loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/query_loader.js +0 -0
- /package/{dist/core → core}/loaders/raw_count_loader.d.ts +0 -0
- /package/{dist/core → core}/loaders/raw_count_loader.js +0 -0
- /package/{dist/core → core}/logger.d.ts +0 -0
- /package/{dist/core → core}/logger.js +0 -0
- /package/{dist/core → core}/privacy.d.ts +0 -0
- /package/{dist/core → core}/privacy.js +0 -0
- /package/{dist/core → core}/query/assoc_query.d.ts +0 -0
- /package/{dist/core → core}/query/assoc_query.js +0 -0
- /package/{dist/core → core}/query/custom_clause_query.d.ts +0 -0
- /package/{dist/core → core}/query/custom_clause_query.js +0 -0
- /package/{dist/core → core}/query/custom_query.d.ts +0 -0
- /package/{dist/core → core}/query/custom_query.js +0 -0
- /package/{dist/core → core}/query/index.d.ts +0 -0
- /package/{dist/core → core}/query/index.js +0 -0
- /package/{dist/core → core}/query/query.d.ts +0 -0
- /package/{dist/core → core}/query/query.js +0 -0
- /package/{dist/core → core}/query_impl.d.ts +0 -0
- /package/{dist/core → core}/query_impl.js +0 -0
- /package/{dist/core → core}/viewer.d.ts +0 -0
- /package/{dist/core → core}/viewer.js +0 -0
- /package/{dist/graphql → graphql}/builtins/connection.d.ts +0 -0
- /package/{dist/graphql → graphql}/builtins/connection.js +0 -0
- /package/{dist/graphql → graphql}/builtins/edge.d.ts +0 -0
- /package/{dist/graphql → graphql}/builtins/edge.js +0 -0
- /package/{dist/graphql → graphql}/builtins/node.d.ts +0 -0
- /package/{dist/graphql → graphql}/builtins/node.js +0 -0
- /package/{dist/graphql → graphql}/graphql.d.ts +0 -0
- /package/{dist/graphql → graphql}/graphql.js +0 -0
- /package/{dist/graphql → graphql}/graphql_field_helpers.d.ts +0 -0
- /package/{dist/graphql → graphql}/graphql_field_helpers.js +0 -0
- /package/{dist/graphql → graphql}/index.d.ts +0 -0
- /package/{dist/graphql → graphql}/index.js +0 -0
- /package/{dist/graphql → graphql}/mutations/union.d.ts +0 -0
- /package/{dist/graphql → graphql}/mutations/union.js +0 -0
- /package/{dist/graphql → graphql}/node_resolver.d.ts +0 -0
- /package/{dist/graphql → graphql}/node_resolver.js +0 -0
- /package/{dist/graphql → graphql}/query/connection_type.d.ts +0 -0
- /package/{dist/graphql → graphql}/query/connection_type.js +0 -0
- /package/{dist/graphql → graphql}/query/edge_connection.d.ts +0 -0
- /package/{dist/graphql → graphql}/query/edge_connection.js +0 -0
- /package/{dist/graphql → graphql}/query/page_info.d.ts +0 -0
- /package/{dist/graphql → graphql}/query/page_info.js +0 -0
- /package/{dist/graphql → graphql}/query/shared_edge_connection.d.ts +0 -0
- /package/{dist/graphql → graphql}/query/shared_edge_connection.js +0 -0
- /package/{dist/graphql → graphql}/scalars/orderby_direction.d.ts +0 -0
- /package/{dist/graphql → graphql}/scalars/orderby_direction.js +0 -0
- /package/{dist/graphql → graphql}/scalars/time.d.ts +0 -0
- /package/{dist/graphql → graphql}/scalars/time.js +0 -0
- /package/{dist/imports → imports}/dataz/example1/_auth.d.ts +0 -0
- /package/{dist/imports → imports}/dataz/example1/_auth.js +0 -0
- /package/{dist/imports → imports}/dataz/example1/_viewer.d.ts +0 -0
- /package/{dist/imports → imports}/dataz/example1/_viewer.js +0 -0
- /package/{dist/imports → imports}/index.d.ts +0 -0
- /package/{dist/imports → imports}/index.js +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/index.js → index.js} +0 -0
- /package/{dist/parse_schema → parse_schema}/parse.d.ts +0 -0
- /package/{dist/parse_schema → parse_schema}/parse.js +0 -0
- /package/{dist/schema → schema}/base_schema.d.ts +0 -0
- /package/{dist/schema → schema}/base_schema.js +0 -0
- /package/{dist/schema → schema}/field.d.ts +0 -0
- /package/{dist/schema → schema}/field.js +0 -0
- /package/{dist/schema → schema}/index.d.ts +0 -0
- /package/{dist/schema → schema}/index.js +0 -0
- /package/{dist/schema → schema}/json_field.d.ts +0 -0
- /package/{dist/schema → schema}/json_field.js +0 -0
- /package/{dist/schema → schema}/schema.d.ts +0 -0
- /package/{dist/schema → schema}/schema.js +0 -0
- /package/{dist/schema → schema}/struct_field.d.ts +0 -0
- /package/{dist/schema → schema}/struct_field.js +0 -0
- /package/{dist/schema → schema}/union_field.d.ts +0 -0
- /package/{dist/schema → schema}/union_field.js +0 -0
- /package/{dist/scripts → scripts}/custom_compiler.d.ts +0 -0
- /package/{dist/scripts → scripts}/custom_compiler.js +0 -0
- /package/{dist/scripts → scripts}/custom_graphql.d.ts +0 -0
- /package/{dist/scripts → scripts}/custom_graphql.js +0 -0
- /package/{dist/scripts → scripts}/migrate_v0.1.d.ts +0 -0
- /package/{dist/scripts → scripts}/migrate_v0.1.js +0 -0
- /package/{dist/scripts → scripts}/move_types.d.ts +0 -0
- /package/{dist/scripts → scripts}/move_types.js +0 -0
- /package/{dist/scripts → scripts}/read_schema.d.ts +0 -0
- /package/{dist/scripts → scripts}/read_schema.js +0 -0
- /package/{dist/testutils → testutils}/action/complex_schemas.d.ts +0 -0
- /package/{dist/testutils → testutils}/action/complex_schemas.js +0 -0
- /package/{dist/testutils → testutils}/builder.d.ts +0 -0
- /package/{dist/testutils → testutils}/builder.js +0 -0
- /package/{dist/testutils → testutils}/context/test_context.d.ts +0 -0
- /package/{dist/testutils → testutils}/context/test_context.js +0 -0
- /package/{dist/testutils → testutils}/db/fixture.d.ts +0 -0
- /package/{dist/testutils → testutils}/db/fixture.js +0 -0
- /package/{dist/testutils → testutils}/db/temp_db.d.ts +0 -0
- /package/{dist/testutils → testutils}/db/temp_db.js +0 -0
- /package/{dist/testutils → testutils}/db/value.d.ts +0 -0
- /package/{dist/testutils → testutils}/db/value.js +0 -0
- /package/{dist/testutils → testutils}/db_mock.d.ts +0 -0
- /package/{dist/testutils → testutils}/db_mock.js +0 -0
- /package/{dist/testutils → testutils}/db_time_zone.d.ts +0 -0
- /package/{dist/testutils → testutils}/db_time_zone.js +0 -0
- /package/{dist/testutils → testutils}/ent-graphql-tests/index.d.ts +0 -0
- /package/{dist/testutils → testutils}/ent-graphql-tests/index.js +0 -0
- /package/{dist/testutils → testutils}/fake_comms.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_comms.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/const.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/const.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/events_query.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/events_query.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_contact.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_contact.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_event.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_event.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_tag.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_tag.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_user.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/fake_user.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/index.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/index.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/internal.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/internal.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/tag_query.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/tag_query.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/test_helpers.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/test_helpers.js +0 -0
- /package/{dist/testutils → testutils}/fake_data/user_query.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_data/user_query.js +0 -0
- /package/{dist/testutils → testutils}/fake_log.d.ts +0 -0
- /package/{dist/testutils → testutils}/fake_log.js +0 -0
- /package/{dist/testutils → testutils}/mock_date.d.ts +0 -0
- /package/{dist/testutils → testutils}/mock_date.js +0 -0
- /package/{dist/testutils → testutils}/mock_log.d.ts +0 -0
- /package/{dist/testutils → testutils}/mock_log.js +0 -0
- /package/{dist/testutils → testutils}/parse_sql.d.ts +0 -0
- /package/{dist/testutils → testutils}/parse_sql.js +0 -0
- /package/{dist/testutils → testutils}/test_edge_global_schema.d.ts +0 -0
- /package/{dist/testutils → testutils}/test_edge_global_schema.js +0 -0
- /package/{dist/testutils → testutils}/write.d.ts +0 -0
- /package/{dist/testutils → testutils}/write.js +0 -0
- /package/{dist/tsc → tsc}/ast.d.ts +0 -0
- /package/{dist/tsc → tsc}/ast.js +0 -0
- /package/{dist/tsc → tsc}/compilerOptions.d.ts +0 -0
- /package/{dist/tsc → tsc}/compilerOptions.js +0 -0
- /package/{dist/tsc → tsc}/move_generated.d.ts +0 -0
- /package/{dist/tsc → tsc}/move_generated.js +0 -0
- /package/{dist/tsc → tsc}/transform.d.ts +0 -0
- /package/{dist/tsc → tsc}/transform.js +0 -0
- /package/{dist/tsc → tsc}/transform_action.d.ts +0 -0
- /package/{dist/tsc → tsc}/transform_action.js +0 -0
- /package/{dist/tsc → tsc}/transform_ent.d.ts +0 -0
- /package/{dist/tsc → tsc}/transform_ent.js +0 -0
- /package/{dist/tsc → tsc}/transform_schema.d.ts +0 -0
- /package/{dist/tsc → tsc}/transform_schema.js +0 -0
package/src/schema/field.ts
DELETED
|
@@ -1,1087 +0,0 @@
|
|
|
1
|
-
import { DateTime } from "luxon";
|
|
2
|
-
import { camelCase } from "camel-case";
|
|
3
|
-
import { isPromise } from "util/types";
|
|
4
|
-
import { validate } from "uuid";
|
|
5
|
-
import { Ent, WriteOperation } from "../core/base";
|
|
6
|
-
import { Builder } from "../action/action";
|
|
7
|
-
import DB, { Dialect } from "../core/db";
|
|
8
|
-
import {
|
|
9
|
-
DBType,
|
|
10
|
-
Field,
|
|
11
|
-
FieldMap,
|
|
12
|
-
FieldOptions,
|
|
13
|
-
ForeignKey,
|
|
14
|
-
PolymorphicOptions,
|
|
15
|
-
Type,
|
|
16
|
-
} from "./schema";
|
|
17
|
-
import { __getGlobalSchemaField } from "../core/global_schema";
|
|
18
|
-
import { log } from "../core/logger";
|
|
19
|
-
|
|
20
|
-
export abstract class BaseField {
|
|
21
|
-
name: string;
|
|
22
|
-
nullable?: boolean;
|
|
23
|
-
storageKey?: string;
|
|
24
|
-
serverDefault?: any;
|
|
25
|
-
unique?: boolean;
|
|
26
|
-
hideFromGraphQL?: boolean;
|
|
27
|
-
private?: boolean;
|
|
28
|
-
sensitive?: boolean;
|
|
29
|
-
graphqlName?: string;
|
|
30
|
-
index?: boolean;
|
|
31
|
-
foreignKey?: ForeignKey;
|
|
32
|
-
|
|
33
|
-
// this should only be set on id fields. if set on other fields, it's currently ignored
|
|
34
|
-
polymorphic?: boolean | PolymorphicOptions;
|
|
35
|
-
// also adds a _type field
|
|
36
|
-
// e.g. owner_id -> owner_type
|
|
37
|
-
// other fields
|
|
38
|
-
|
|
39
|
-
// fields derived from this one. e.g. polymorphic id fields
|
|
40
|
-
// add a _type field
|
|
41
|
-
// e.g. a polymorphic user_id field adds a user_type field
|
|
42
|
-
// derivedFields?(name: string): FieldMap;
|
|
43
|
-
derivedWhenEmbedded?: boolean;
|
|
44
|
-
|
|
45
|
-
logValue(val: any): any {
|
|
46
|
-
if (this.sensitive) {
|
|
47
|
-
// for sensitive things, don't log the actual value
|
|
48
|
-
return "*".repeat(`${val}`.length);
|
|
49
|
-
}
|
|
50
|
-
return val;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export class UUIDField extends BaseField implements Field {
|
|
55
|
-
type: Type = { dbType: DBType.UUID };
|
|
56
|
-
|
|
57
|
-
constructor(private options?: FieldOptions) {
|
|
58
|
-
super();
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
options?.fieldEdge?.enforceSchema &&
|
|
62
|
-
!options.fieldEdge.getLoaderInfoFromSchema
|
|
63
|
-
) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`cannot enforceSchema if getLoaderInfoFromSchema wasn't passed in`,
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getDerivedFields(fieldName: string): FieldMap {
|
|
71
|
-
const polymorphic = this.options?.polymorphic;
|
|
72
|
-
if (polymorphic) {
|
|
73
|
-
let name = "";
|
|
74
|
-
if (fieldName.endsWith("_id")) {
|
|
75
|
-
let idx = fieldName.indexOf("_id");
|
|
76
|
-
name = fieldName.substring(0, idx) + "_type";
|
|
77
|
-
} else if (fieldName.endsWith("ID")) {
|
|
78
|
-
let idx = fieldName.indexOf("ID");
|
|
79
|
-
name = fieldName.substring(0, idx) + "Type";
|
|
80
|
-
} else {
|
|
81
|
-
throw new Error(`unsupported id polymorhpic type ${fieldName}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let types: string[] | undefined;
|
|
85
|
-
let serverDefault: any = undefined;
|
|
86
|
-
if (typeof polymorphic === "object") {
|
|
87
|
-
serverDefault = polymorphic.serverDefault;
|
|
88
|
-
types = polymorphic.types;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// polymorphic field automatically hidden from GraphQL
|
|
92
|
-
// can be made visible with custom fields if user wants to change this behavior
|
|
93
|
-
// can't be foreignKey so need to make other changes to the field
|
|
94
|
-
// intentionally not made private as it doesn't seem like it needs to be hidden
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
[name]: PolymorphicStringType({
|
|
98
|
-
types: types,
|
|
99
|
-
hideFromGraphQL: true,
|
|
100
|
-
derivedWhenEmbedded: true,
|
|
101
|
-
nullable: this.options?.nullable,
|
|
102
|
-
parentFieldToValidate: fieldName,
|
|
103
|
-
serverDefault: serverDefault,
|
|
104
|
-
}),
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
return {};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private isBuilder(val: Builder<Ent> | any): val is Builder<Ent> {
|
|
111
|
-
return (val as Builder<Ent>).placeholderID !== undefined;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async valid(val: any) {
|
|
115
|
-
if (typeof val === "string" && !validate(val)) {
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
if (!this.options?.fieldEdge?.enforceSchema) {
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const getLoaderInfo = this.options.fieldEdge.getLoaderInfoFromSchema!;
|
|
123
|
-
const loaderInfo = getLoaderInfo(this.options.fieldEdge.schema);
|
|
124
|
-
if (!loaderInfo) {
|
|
125
|
-
throw new Error(
|
|
126
|
-
`couldn't get loaderInfo for ${this.options.fieldEdge.schema}`,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
if (this.isBuilder(val)) {
|
|
130
|
-
// if builder, the nodeType of the builder and the nodeType of the loaderInfo should match
|
|
131
|
-
return val.nodeType === loaderInfo.nodeType;
|
|
132
|
-
}
|
|
133
|
-
// TODO we need context here to make sure that we hit local cache
|
|
134
|
-
|
|
135
|
-
const row = await loaderInfo.loaderFactory.createLoader().load(val);
|
|
136
|
-
return row !== null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export function UUIDType(options?: FieldOptions): UUIDField {
|
|
141
|
-
let result = new UUIDField(options);
|
|
142
|
-
return Object.assign(result, options);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export interface IntegerOptions extends NumberOptions<number> {}
|
|
146
|
-
|
|
147
|
-
export interface NumberOptions<T> extends FieldOptions {
|
|
148
|
-
min?: T;
|
|
149
|
-
max?: T;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export class NumberField<T> extends BaseField {
|
|
153
|
-
// to be overriden as needed
|
|
154
|
-
type: Type = { dbType: DBType.Int };
|
|
155
|
-
|
|
156
|
-
private validators: { (str: number): boolean }[] = [];
|
|
157
|
-
private options: NumberOptions<T> = {};
|
|
158
|
-
|
|
159
|
-
constructor(options?: NumberOptions<T>) {
|
|
160
|
-
super();
|
|
161
|
-
// for legacy callers
|
|
162
|
-
this.handleOptions(options || this.options);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
getOptions(): NumberOptions<T> {
|
|
166
|
-
return this.options;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
private handleOptions(options: NumberOptions<T>) {
|
|
170
|
-
const params = {
|
|
171
|
-
min: this.min,
|
|
172
|
-
max: this.max,
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
for (const k in params) {
|
|
176
|
-
const v = options[k];
|
|
177
|
-
if (v !== undefined) {
|
|
178
|
-
params[k].apply(this, [v]);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
this.options = options;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
min(l: T): this {
|
|
185
|
-
// @ts-ignore Operator '>=' cannot be applied to types 'number' and 'T'.
|
|
186
|
-
return this.validate((val) => val >= l);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
max(l: T): this {
|
|
190
|
-
// @ts-ignore Operator '<=' cannot be applied to types 'number' and 'T'.
|
|
191
|
-
return this.validate((val) => val <= l);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
valid(val: any): boolean {
|
|
195
|
-
for (const validator of this.validators) {
|
|
196
|
-
if (!validator(val)) {
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
validate(validator: (str: number) => boolean): this {
|
|
204
|
-
this.validators.push(validator);
|
|
205
|
-
return this;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export class IntegerField extends NumberField<number> implements Field {
|
|
210
|
-
type: Type = { dbType: DBType.Int };
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export function IntegerType(options?: IntegerOptions): IntegerField {
|
|
214
|
-
let result = new IntegerField(options);
|
|
215
|
-
return Object.assign(result, options);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
export class BigIntegerField extends NumberField<BigInt> implements Field {
|
|
219
|
-
type: Type = { dbType: DBType.BigInt };
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export function BigIntegerType(
|
|
223
|
-
options?: NumberOptions<BigInt>,
|
|
224
|
-
): BigIntegerField {
|
|
225
|
-
let result = new BigIntegerField(options);
|
|
226
|
-
return Object.assign(result, options);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export class FloatField extends NumberField<number> implements Field {
|
|
230
|
-
type: Type = { dbType: DBType.Float };
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function FloatType(options?: NumberOptions<number>): FloatField {
|
|
234
|
-
let result = new FloatField(options);
|
|
235
|
-
return Object.assign(result, options);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export class BooleanField extends BaseField implements Field {
|
|
239
|
-
type: Type = { dbType: DBType.Boolean };
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export function BooleanType(options?: FieldOptions): BooleanField {
|
|
243
|
-
let result = new BooleanField();
|
|
244
|
-
return Object.assign(result, options);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export interface StringOptions extends FieldOptions {
|
|
248
|
-
minLen?: number;
|
|
249
|
-
maxLen?: number;
|
|
250
|
-
length?: number;
|
|
251
|
-
toLowerCase?: boolean;
|
|
252
|
-
toUpperCase?: boolean;
|
|
253
|
-
match?: string | RegExp;
|
|
254
|
-
doesNotMatch?: string | RegExp;
|
|
255
|
-
trim?: boolean;
|
|
256
|
-
trimLeft?: boolean;
|
|
257
|
-
trimRight?: boolean;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export class StringField extends BaseField implements Field {
|
|
261
|
-
type: Type = { dbType: DBType.String };
|
|
262
|
-
private validators: { (str: string): boolean }[] = [];
|
|
263
|
-
private formatters: { (str: string): string }[] = [];
|
|
264
|
-
private options: StringOptions = {};
|
|
265
|
-
|
|
266
|
-
constructor(options?: StringOptions) {
|
|
267
|
-
super();
|
|
268
|
-
// for legacy callers
|
|
269
|
-
this.handleOptions(options || {});
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
getOptions(): StringOptions {
|
|
273
|
-
return this.options;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
private handleOptions(options: StringOptions) {
|
|
277
|
-
const noParams = {
|
|
278
|
-
toLowerCase: this.toLowerCase,
|
|
279
|
-
toUpperCase: this.toUpperCase,
|
|
280
|
-
trim: this.trim,
|
|
281
|
-
trimLeft: this.trimLeft,
|
|
282
|
-
trimRight: this.trimRight,
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
const params = {
|
|
286
|
-
minLen: this.minLen,
|
|
287
|
-
maxLen: this.maxLen,
|
|
288
|
-
length: this.length,
|
|
289
|
-
match: this.match,
|
|
290
|
-
doesNotMatch: this.doesNotMatch,
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
for (const k in params) {
|
|
294
|
-
const v = options[k];
|
|
295
|
-
if (v !== undefined) {
|
|
296
|
-
params[k].apply(this, [v]);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
for (const k in noParams) {
|
|
300
|
-
if (options[k] === true) {
|
|
301
|
-
noParams[k].apply(this);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
this.options = options;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
minLen(l: number): this {
|
|
308
|
-
return this.validate((val) => {
|
|
309
|
-
return val.length >= l;
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
maxLen(l: number): this {
|
|
314
|
-
return this.validate((val) => val.length <= l);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
length(l: number) {
|
|
318
|
-
return this.validate((val) => val.length === l);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
valid(val: any): boolean {
|
|
322
|
-
// TODO play with API more and figure out if I want functions ala below
|
|
323
|
-
// or properties ala this
|
|
324
|
-
// both doable but which API is better ?
|
|
325
|
-
for (const validator of this.validators) {
|
|
326
|
-
if (!validator(val)) {
|
|
327
|
-
return false;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
format(val: any): any {
|
|
334
|
-
for (const formatter of this.formatters) {
|
|
335
|
-
val = formatter(val);
|
|
336
|
-
}
|
|
337
|
-
return val;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
validate(validator: (str: string) => boolean): this {
|
|
341
|
-
this.validators.push(validator);
|
|
342
|
-
return this;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
formatter(formatter: (str: string) => string): this {
|
|
346
|
-
this.formatters.push(formatter);
|
|
347
|
-
return this;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
match(pattern: string | RegExp): this {
|
|
351
|
-
return this.validate(function (str: string): boolean {
|
|
352
|
-
let r = new RegExp(pattern);
|
|
353
|
-
return r.test(str);
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
doesNotMatch(pattern: string | RegExp): this {
|
|
358
|
-
return this.validate(function (str: string): boolean {
|
|
359
|
-
let r = new RegExp(pattern);
|
|
360
|
-
return !r.test(str);
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
toLowerCase(): this {
|
|
365
|
-
return this.formatter((str) => str.toLowerCase());
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
toUpperCase(): this {
|
|
369
|
-
return this.formatter((str) => str.toUpperCase());
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
trim(): this {
|
|
373
|
-
return this.formatter((str) => str.trim());
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
trimLeft(): this {
|
|
377
|
-
return this.formatter((str) => str.trimLeft());
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
trimRight(): this {
|
|
381
|
-
return this.formatter((str) => str.trimRight());
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
interface PolymorphicStringOptions extends StringOptions {
|
|
386
|
-
parentFieldToValidate: string;
|
|
387
|
-
// restrict to just these types...
|
|
388
|
-
types?: string[];
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
export class PolymorphicStringField extends StringField {
|
|
392
|
-
private camelCaseVals: string[] | undefined;
|
|
393
|
-
constructor(private opts: PolymorphicStringOptions) {
|
|
394
|
-
super(opts);
|
|
395
|
-
if (opts.types) {
|
|
396
|
-
this.camelCaseVals = opts.types.map((v) => camelCase(v));
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
validateWithFullData(val: any, b: Builder<any>): boolean {
|
|
401
|
-
const input = b.getInput();
|
|
402
|
-
const inputKey =
|
|
403
|
-
b.orchestrator.__getOptions().fieldInfo[this.opts.parentFieldToValidate]
|
|
404
|
-
.inputKey;
|
|
405
|
-
|
|
406
|
-
const v = input[inputKey];
|
|
407
|
-
|
|
408
|
-
if (val === null) {
|
|
409
|
-
// if this is being set to null, ok if v is also null
|
|
410
|
-
return v === null;
|
|
411
|
-
}
|
|
412
|
-
// if this is not being set, ok if v is not being set
|
|
413
|
-
if (val === undefined && b.operation === WriteOperation.Insert) {
|
|
414
|
-
return v === undefined;
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
valid(val: any): boolean {
|
|
420
|
-
if (!this.camelCaseVals) {
|
|
421
|
-
return true;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
let str = camelCase(String(val));
|
|
425
|
-
// allow different cases because it could be coming from different clients who don't have strong typing
|
|
426
|
-
return this.camelCaseVals.some((value) => value === str);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
format(val: any) {
|
|
430
|
-
if (!this.camelCaseVals) {
|
|
431
|
-
return val;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
const converted = camelCase(String(val));
|
|
435
|
-
|
|
436
|
-
for (const v of this.camelCaseVals) {
|
|
437
|
-
if (v === val) {
|
|
438
|
-
return val;
|
|
439
|
-
}
|
|
440
|
-
if (converted === v) {
|
|
441
|
-
return converted;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return val;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
function PolymorphicStringType(opts: PolymorphicStringOptions) {
|
|
449
|
-
let result = new PolymorphicStringField(opts);
|
|
450
|
-
return Object.assign(result, opts);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
export function StringType(options?: StringOptions): StringField {
|
|
454
|
-
let result = new StringField(options);
|
|
455
|
-
const options2 = { ...options };
|
|
456
|
-
for (const key in options) {
|
|
457
|
-
// key already exists here e.g. the method toLowerCase
|
|
458
|
-
if (result[key]) {
|
|
459
|
-
delete options2[key];
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
return Object.assign(result, options2);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
export interface TimestampOptions extends FieldOptions {
|
|
466
|
-
withTimezone?: boolean;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
export class TimestampField extends BaseField implements Field {
|
|
470
|
-
type: Type = { dbType: DBType.Timestamp };
|
|
471
|
-
withTimezone?: boolean;
|
|
472
|
-
|
|
473
|
-
constructor(options: TimestampOptions) {
|
|
474
|
-
super();
|
|
475
|
-
if (options.withTimezone) {
|
|
476
|
-
this.type = {
|
|
477
|
-
dbType: DBType.Timestamptz,
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
format(val: Date): any {
|
|
483
|
-
let dt: DateTime;
|
|
484
|
-
if (typeof val === "string") {
|
|
485
|
-
dt = DateTime.fromISO(val);
|
|
486
|
-
} else {
|
|
487
|
-
dt = DateTime.fromJSDate(val);
|
|
488
|
-
}
|
|
489
|
-
if (this.withTimezone) {
|
|
490
|
-
// send ISO down so that if it's saved in different format e.g. csv and then
|
|
491
|
-
// later saved in the db e.g. with COPY, correct value is saved.
|
|
492
|
-
return dt.toISO();
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// without timezone, make sure to store UTC value...
|
|
496
|
-
return dt.toUTC().toISO();
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
export function TimestampType(options?: TimestampOptions): TimestampField {
|
|
501
|
-
let result = new TimestampField({ ...options });
|
|
502
|
-
return Object.assign(result, options);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
export function TimestamptzType(options?: FieldOptions): TimestampField {
|
|
506
|
-
let opts: TimestampOptions = { withTimezone: true, ...options };
|
|
507
|
-
let result = new TimestampField(opts);
|
|
508
|
-
return Object.assign(result, opts);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
export interface TimeOptions extends FieldOptions {
|
|
512
|
-
withTimezone?: boolean;
|
|
513
|
-
precision?: number;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
export const leftPad = (val: number): string => {
|
|
517
|
-
if (val >= 0) {
|
|
518
|
-
if (val < 10) {
|
|
519
|
-
return `0${val}`;
|
|
520
|
-
}
|
|
521
|
-
return val.toString();
|
|
522
|
-
}
|
|
523
|
-
if (val > -10) {
|
|
524
|
-
return `-0${val * -1}`;
|
|
525
|
-
}
|
|
526
|
-
return val.toString();
|
|
527
|
-
};
|
|
528
|
-
|
|
529
|
-
export class TimeField extends BaseField implements Field {
|
|
530
|
-
type: Type = { dbType: DBType.Time };
|
|
531
|
-
withTimezone?: boolean;
|
|
532
|
-
|
|
533
|
-
constructor(options?: TimeOptions) {
|
|
534
|
-
super();
|
|
535
|
-
if (options?.withTimezone) {
|
|
536
|
-
this.type = {
|
|
537
|
-
dbType: DBType.Timetz,
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
format(val: any): any {
|
|
543
|
-
// allow database handle it
|
|
544
|
-
// https://www.postgresql.org/docs/9.1/datatype-datetime.html#AEN5668
|
|
545
|
-
if (!(val instanceof Date)) {
|
|
546
|
-
return val;
|
|
547
|
-
}
|
|
548
|
-
let offset = "";
|
|
549
|
-
|
|
550
|
-
if (this.withTimezone) {
|
|
551
|
-
// for some reason this API is backwards
|
|
552
|
-
let div = (val.getTimezoneOffset() / 60) * -1;
|
|
553
|
-
|
|
554
|
-
offset = leftPad(div);
|
|
555
|
-
}
|
|
556
|
-
let hh = leftPad(val.getHours());
|
|
557
|
-
let mm = leftPad(val.getMinutes());
|
|
558
|
-
let ss = leftPad(val.getSeconds());
|
|
559
|
-
let ms = leftPad(val.getMilliseconds());
|
|
560
|
-
if (ms !== "00" && offset) {
|
|
561
|
-
return `${hh}:${mm}:${ss}.${ms}${offset}`;
|
|
562
|
-
} else {
|
|
563
|
-
return `${hh}:${mm}:${ss}`;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
export function TimeType(options?: TimeOptions): TimeField {
|
|
569
|
-
let result = new TimeField(options);
|
|
570
|
-
return Object.assign(result, options);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
export function TimetzType(options?: FieldOptions): TimeField {
|
|
574
|
-
let opts: TimestampOptions = {
|
|
575
|
-
withTimezone: true,
|
|
576
|
-
...options,
|
|
577
|
-
};
|
|
578
|
-
let result = new TimeField(opts);
|
|
579
|
-
return Object.assign(result, opts);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
export class DateField extends BaseField implements Field {
|
|
583
|
-
type: Type = { dbType: DBType.Date };
|
|
584
|
-
|
|
585
|
-
format(val: any): any {
|
|
586
|
-
if (typeof val === "string") {
|
|
587
|
-
return val;
|
|
588
|
-
}
|
|
589
|
-
val = new Date(val);
|
|
590
|
-
|
|
591
|
-
let yy = leftPad(val.getFullYear());
|
|
592
|
-
|
|
593
|
-
// lol this API
|
|
594
|
-
// for some reason this is 0-index
|
|
595
|
-
let mm = leftPad(val.getMonth() + 1);
|
|
596
|
-
let dd = leftPad(val.getDate());
|
|
597
|
-
let ret = `${yy}-${mm}-${dd}`;
|
|
598
|
-
|
|
599
|
-
return ret;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
export function DateType(options?: FieldOptions): DateField {
|
|
604
|
-
let result = new DateField();
|
|
605
|
-
return Object.assign(result, options);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
declare type StringEnumMap = {
|
|
609
|
-
[key: string]: string;
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* @deprecated use StringEnumOptions
|
|
614
|
-
*/
|
|
615
|
-
export interface EnumOptions extends FieldOptions {
|
|
616
|
-
// required when not a reference to a lookup table
|
|
617
|
-
// when using a lookup table enum, we should use all caps because we don't have the values to translate back
|
|
618
|
-
values?: string[];
|
|
619
|
-
// used when we're migrating from old -> new values and want to reuse the values but the values may not be the best keys so this is preferred
|
|
620
|
-
// instead of values.
|
|
621
|
-
// GRAPHQL will take the key and use it as the value here instead o
|
|
622
|
-
map?: StringEnumMap;
|
|
623
|
-
|
|
624
|
-
// by default the type is the name as the field
|
|
625
|
-
// it's recommended to scope the enum names in scenarios where it makes sense
|
|
626
|
-
tsType?: string;
|
|
627
|
-
graphQLType?: string;
|
|
628
|
-
|
|
629
|
-
createEnumType?: boolean;
|
|
630
|
-
|
|
631
|
-
// if set to true, we don't add an `UNKNOWN` or `Unknown` type to deal with invalid|deprecated|old types
|
|
632
|
-
// coming from the db.
|
|
633
|
-
// GraphQL is strict about old values so we are adding this
|
|
634
|
-
disableUnknownType?: boolean;
|
|
635
|
-
|
|
636
|
-
// used to flag that this is referencing a global shared enum type.
|
|
637
|
-
globalType?: string;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* @deprecated Use StringEnumField
|
|
642
|
-
*/
|
|
643
|
-
export class EnumField extends BaseField implements Field {
|
|
644
|
-
type: Type;
|
|
645
|
-
private values?: string[];
|
|
646
|
-
private map?: StringEnumMap;
|
|
647
|
-
|
|
648
|
-
constructor(options: StringEnumOptions) {
|
|
649
|
-
super();
|
|
650
|
-
this.type = {
|
|
651
|
-
// if createEnumType boolean, we create postgres enum otherwise we use a string for it
|
|
652
|
-
dbType: options.createEnumType ? DBType.Enum : DBType.StringEnum,
|
|
653
|
-
values: options.values,
|
|
654
|
-
enumMap: options.map,
|
|
655
|
-
type: options.tsType,
|
|
656
|
-
graphQLType: options.graphQLType,
|
|
657
|
-
disableUnknownType: options.disableUnknownType,
|
|
658
|
-
globalType: options.globalType,
|
|
659
|
-
};
|
|
660
|
-
if (!options.foreignKey) {
|
|
661
|
-
if (!options.values && !options.map && !options.globalType) {
|
|
662
|
-
throw new Error(
|
|
663
|
-
"values, map or globalType required if not look up table enum. Look-up table enum indicated by foreignKey field",
|
|
664
|
-
);
|
|
665
|
-
}
|
|
666
|
-
if (options.values) {
|
|
667
|
-
if (!options.values.length) {
|
|
668
|
-
throw new Error("need at least one value in enum type");
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
if (options.map) {
|
|
672
|
-
let count = 0;
|
|
673
|
-
for (const _ in options.map) {
|
|
674
|
-
count++;
|
|
675
|
-
break;
|
|
676
|
-
}
|
|
677
|
-
if (!count) {
|
|
678
|
-
throw new Error("need at least one entry in enum map");
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
} else {
|
|
682
|
-
if (options.values || options.map || options.globalType) {
|
|
683
|
-
throw new Error(
|
|
684
|
-
"cannot specify values, map or globalType and foreign key for lookup table enum type",
|
|
685
|
-
);
|
|
686
|
-
}
|
|
687
|
-
if (options.createEnumType) {
|
|
688
|
-
throw new Error(
|
|
689
|
-
"cannot specify createEnumType without specifying values",
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
if (options.tsType) {
|
|
693
|
-
throw new Error("cannot specify tsType without specifying values");
|
|
694
|
-
}
|
|
695
|
-
if (options.graphQLType) {
|
|
696
|
-
throw new Error("cannot specify graphQLType without specifying values");
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
this.values = options.values;
|
|
700
|
-
this.map = options.map;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
async valid(val: any): Promise<boolean> {
|
|
704
|
-
if (this.type.globalType) {
|
|
705
|
-
const f = __getGlobalSchemaField(this.type.globalType);
|
|
706
|
-
if (f) {
|
|
707
|
-
if (f.valid) {
|
|
708
|
-
return f.valid(val);
|
|
709
|
-
}
|
|
710
|
-
return true;
|
|
711
|
-
} else {
|
|
712
|
-
log(
|
|
713
|
-
"error",
|
|
714
|
-
`globalType ${this.type.globalType} not found in global schema`,
|
|
715
|
-
);
|
|
716
|
-
return false;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// lookup table enum and indicated via presence of foreignKey
|
|
721
|
-
if (!this.values && !this.map) {
|
|
722
|
-
return true;
|
|
723
|
-
}
|
|
724
|
-
if (this.values) {
|
|
725
|
-
let str = String(val);
|
|
726
|
-
return this.values.some((value) => value === str);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
for (const k in this.map) {
|
|
730
|
-
const v = this.map[k];
|
|
731
|
-
if (v === val) {
|
|
732
|
-
return true;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
return false;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
format(val: any): any {
|
|
739
|
-
if (this.type.globalType) {
|
|
740
|
-
const f = __getGlobalSchemaField(this.type.globalType);
|
|
741
|
-
if (f && f.format) {
|
|
742
|
-
return f.format(val);
|
|
743
|
-
}
|
|
744
|
-
return val;
|
|
745
|
-
}
|
|
746
|
-
return val;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
export class StringEnumField extends EnumField {}
|
|
751
|
-
|
|
752
|
-
export interface PolymorphicStringEnumOptions extends EnumOptions {
|
|
753
|
-
parentFieldToValidate: string;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
export interface StringEnumOptions extends EnumOptions {}
|
|
757
|
-
|
|
758
|
-
export function EnumType(options: StringEnumOptions): EnumField {
|
|
759
|
-
let result = new StringEnumField(options);
|
|
760
|
-
return Object.assign(result, options);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
declare type IntEnumMap = {
|
|
764
|
-
[key: string]: number;
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
export interface IntegerEnumOptions extends FieldOptions {
|
|
768
|
-
// used when we're migrating from old -> new values and want to reuse the values but the values may not be the best keys so this is preferred
|
|
769
|
-
// instead of values.
|
|
770
|
-
// GRAPHQL will take the key and use it as the value here instead o
|
|
771
|
-
map?: IntEnumMap;
|
|
772
|
-
deprecated?: IntEnumMap;
|
|
773
|
-
|
|
774
|
-
// by default the type is the name as the field
|
|
775
|
-
// it's recommended to scope the enum names in scenarios where it makes sense
|
|
776
|
-
tsType?: string;
|
|
777
|
-
graphQLType?: string;
|
|
778
|
-
|
|
779
|
-
// if set to true, we don't add an `UNKNOWN` or `Unknown` type to deal with invalid|deprecated|old types
|
|
780
|
-
// coming from the db.
|
|
781
|
-
// GraphQL is strict about old values so we are adding this
|
|
782
|
-
disableUnknownType?: boolean;
|
|
783
|
-
|
|
784
|
-
// TODO would be nice for typescript to make tsType and graphQLType required
|
|
785
|
-
// when globalType is set
|
|
786
|
-
// hard to do that because FieldOptions allows any field so disjoint `|` types don't work
|
|
787
|
-
globalType?: string;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
export class IntegerEnumField extends BaseField implements Field {
|
|
791
|
-
type: Type;
|
|
792
|
-
private map: IntEnumMap;
|
|
793
|
-
|
|
794
|
-
constructor(options: IntegerEnumOptions) {
|
|
795
|
-
super();
|
|
796
|
-
this.type = {
|
|
797
|
-
dbType: DBType.IntEnum,
|
|
798
|
-
intEnumMap: options.map,
|
|
799
|
-
type: options.tsType,
|
|
800
|
-
graphQLType: options.graphQLType,
|
|
801
|
-
deprecatedIntEnumMap: options.deprecated,
|
|
802
|
-
disableUnknownType: options.disableUnknownType,
|
|
803
|
-
globalType: options.globalType,
|
|
804
|
-
};
|
|
805
|
-
|
|
806
|
-
if (options.foreignKey) {
|
|
807
|
-
throw new Error(`foreignKey on intEnum not supported`);
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
if (options.globalType) {
|
|
811
|
-
if (options.map) {
|
|
812
|
-
throw new Error(`cannot specify map and globalType`);
|
|
813
|
-
}
|
|
814
|
-
this.map = {};
|
|
815
|
-
} else {
|
|
816
|
-
let count = 0;
|
|
817
|
-
for (const _ in options.map) {
|
|
818
|
-
count++;
|
|
819
|
-
break;
|
|
820
|
-
}
|
|
821
|
-
if (!count) {
|
|
822
|
-
throw new Error("need at least one entry in enum map");
|
|
823
|
-
}
|
|
824
|
-
if (!options.map) {
|
|
825
|
-
throw new Error("map required if not globalType");
|
|
826
|
-
}
|
|
827
|
-
this.map = options.map!;
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
async valid(val: any): Promise<boolean> {
|
|
832
|
-
if (this.type?.globalType) {
|
|
833
|
-
const f = __getGlobalSchemaField(this.type.globalType);
|
|
834
|
-
if (f) {
|
|
835
|
-
if (f.valid) {
|
|
836
|
-
return f.valid(val);
|
|
837
|
-
}
|
|
838
|
-
return true;
|
|
839
|
-
} else {
|
|
840
|
-
log(
|
|
841
|
-
"error",
|
|
842
|
-
`globalType ${this.type.globalType} not found in global schema`,
|
|
843
|
-
);
|
|
844
|
-
return false;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
// lookup table enum and indicated via presence of foreignKey
|
|
849
|
-
|
|
850
|
-
for (const k in this.map) {
|
|
851
|
-
const v = this.map[k];
|
|
852
|
-
if (v === val || v === parseInt(val)) {
|
|
853
|
-
return true;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return false;
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
format(val: any): any {
|
|
860
|
-
if (this.type.globalType) {
|
|
861
|
-
const f = __getGlobalSchemaField(this.type.globalType);
|
|
862
|
-
if (f && f.format) {
|
|
863
|
-
return f.format(val);
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
return parseInt(val);
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
export function IntegerEnumType(options: IntegerEnumOptions): IntegerEnumField {
|
|
872
|
-
let result = new IntegerEnumField(options);
|
|
873
|
-
return Object.assign(result, options);
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
interface ListOptions extends FieldOptions {
|
|
877
|
-
disableJSONStringify?: boolean;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
export class ListField extends BaseField {
|
|
881
|
-
type: Type;
|
|
882
|
-
private validators: { (val: any[]): boolean }[] = [];
|
|
883
|
-
|
|
884
|
-
constructor(private field: Field, private options?: ListOptions) {
|
|
885
|
-
super();
|
|
886
|
-
if (field.type.dbType === DBType.List) {
|
|
887
|
-
throw new Error(`nested lists not currently supported`);
|
|
888
|
-
}
|
|
889
|
-
this.type = {
|
|
890
|
-
dbType: DBType.List,
|
|
891
|
-
listElemType: field.type,
|
|
892
|
-
};
|
|
893
|
-
Object.assign(this, options);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
__getElemField() {
|
|
897
|
-
return this.field;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
validate(validator: (val: any[]) => boolean): this {
|
|
901
|
-
this.validators.push(validator);
|
|
902
|
-
return this;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
async valid(val: any) {
|
|
906
|
-
if (!Array.isArray(val)) {
|
|
907
|
-
return false;
|
|
908
|
-
}
|
|
909
|
-
for (const validator of this.validators) {
|
|
910
|
-
if (!validator(val)) {
|
|
911
|
-
return false;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
const valid = this.field.valid;
|
|
915
|
-
if (!valid) {
|
|
916
|
-
return true;
|
|
917
|
-
}
|
|
918
|
-
const res = valid.apply(this.field, [val[0]]);
|
|
919
|
-
if (isPromise(res)) {
|
|
920
|
-
const ret = await Promise.all(
|
|
921
|
-
val.map(async (v) => await valid.apply(this.field, [v])),
|
|
922
|
-
);
|
|
923
|
-
return ret.every((v) => v);
|
|
924
|
-
}
|
|
925
|
-
const ret = val.map((v) => valid.apply(this.field, [v]));
|
|
926
|
-
const result = ret.every((v) => v);
|
|
927
|
-
return result;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
private postgresVal(val: any, jsonType?: boolean) {
|
|
931
|
-
if (!jsonType && val === "") {
|
|
932
|
-
// support empty strings in list
|
|
933
|
-
val = '"' + val + '"';
|
|
934
|
-
return val;
|
|
935
|
-
}
|
|
936
|
-
if (this.options?.disableJSONStringify) {
|
|
937
|
-
return val;
|
|
938
|
-
}
|
|
939
|
-
return JSON.stringify(val);
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
format(val: any, nested?: boolean): any {
|
|
943
|
-
if (!Array.isArray(val)) {
|
|
944
|
-
throw new Error(`need an array to format`);
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
const elemDBType = this.type.listElemType!.dbType;
|
|
948
|
-
const jsonType = elemDBType === "JSON" || elemDBType === "JSONB";
|
|
949
|
-
// postgres ish doesn't apply when nested
|
|
950
|
-
const postgres = !nested && DB.getDialect() === Dialect.Postgres;
|
|
951
|
-
|
|
952
|
-
if (nested && !this.field.format) {
|
|
953
|
-
return val;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
if (!postgres && !this.field.format) {
|
|
957
|
-
return JSON.stringify(val);
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
let ret: any[] = [];
|
|
961
|
-
let postgresRet: string = "{";
|
|
962
|
-
for (let i = 0; i < val.length; i++) {
|
|
963
|
-
let formatted = val[i];
|
|
964
|
-
if (this.field.format) {
|
|
965
|
-
formatted = this.field.format(val[i], nested);
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
// postgres supports arrays natively so we
|
|
969
|
-
// structure it in the expected format
|
|
970
|
-
if (postgres) {
|
|
971
|
-
postgresRet += this.postgresVal(formatted, jsonType);
|
|
972
|
-
if (i !== val.length - 1) {
|
|
973
|
-
postgresRet += ",";
|
|
974
|
-
}
|
|
975
|
-
} else {
|
|
976
|
-
ret[i] = formatted;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
if (postgres) {
|
|
980
|
-
return postgresRet + "}";
|
|
981
|
-
}
|
|
982
|
-
// don't JSON.stringify if nested
|
|
983
|
-
if (nested) {
|
|
984
|
-
return ret;
|
|
985
|
-
}
|
|
986
|
-
return JSON.stringify(ret);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
minLen(l: number): this {
|
|
990
|
-
return this.validate((val: any[]) => val.length >= l);
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
maxLen(l: number): this {
|
|
994
|
-
return this.validate((val: any[]) => val.length <= l);
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
length(l: number): this {
|
|
998
|
-
return this.validate((val: any[]) => val.length === l);
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
// like python's range() function
|
|
1002
|
-
// start is where to start and stop is the number to stop (not inclusive in the range)
|
|
1003
|
-
range(start: any, stop: any): this {
|
|
1004
|
-
return this.validate((val: any[]) => {
|
|
1005
|
-
for (const v of val) {
|
|
1006
|
-
if (v < start || v >= stop) {
|
|
1007
|
-
return false;
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
return true;
|
|
1011
|
-
});
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
export function StringListType(options?: StringOptions) {
|
|
1016
|
-
return new ListField(StringType(options), options);
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
export function IntListType(options?: FieldOptions) {
|
|
1020
|
-
return new ListField(IntegerType(options), options);
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
export function IntegerListType(options?: FieldOptions) {
|
|
1024
|
-
return new ListField(IntegerType(options), options);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
export function FloatListType(options?: FieldOptions) {
|
|
1028
|
-
return new ListField(FloatType(options), options);
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
export function BigIntegerListType(options: FieldOptions) {
|
|
1032
|
-
return new ListField(BigIntegerType(options), options);
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
export function BooleanListType(options?: FieldOptions) {
|
|
1036
|
-
return new ListField(BooleanType(options), options);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
export function TimestampListType(options: TimestampOptions) {
|
|
1040
|
-
return new ListField(TimestampType(options), options);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
export function TimestamptzListType(options?: TimestampOptions) {
|
|
1044
|
-
return new ListField(TimestamptzType(options), options);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
export function TimeListType(options?: TimeOptions) {
|
|
1048
|
-
return new ListField(TimeType(options), options);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
export function TimetzListType(options: TimeOptions) {
|
|
1052
|
-
return new ListField(TimetzType(options), options);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
export function DateListType(options?: FieldOptions) {
|
|
1056
|
-
return new ListField(DateType(options), options);
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
export function EnumListType(options: StringEnumOptions) {
|
|
1060
|
-
if (options.createEnumType) {
|
|
1061
|
-
throw new Error(`createEnumType is currently unsupported in enum list`);
|
|
1062
|
-
}
|
|
1063
|
-
if (options.foreignKey) {
|
|
1064
|
-
throw new Error(`foreignKey is currently unsupported in enum list`);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
// not all of these will make sense in a list...
|
|
1068
|
-
// can make it work eventually but involves work we're not currently trying to do
|
|
1069
|
-
// developer can try to work around it by calling below on their own.
|
|
1070
|
-
// unclear what the behavior is
|
|
1071
|
-
return new ListField(EnumType(options), options);
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
export function IntegerEnumListType(options: IntegerEnumOptions) {
|
|
1075
|
-
// not all of these will make sense in a list...
|
|
1076
|
-
// can make it work eventually but involves work we're not currently trying to do
|
|
1077
|
-
// developer can try to work around it by calling below on their own.
|
|
1078
|
-
// unclear what the behavior is
|
|
1079
|
-
return new ListField(IntegerEnumType(options), options);
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
export function UUIDListType(options?: FieldOptions) {
|
|
1083
|
-
return new ListField(UUIDType(options), {
|
|
1084
|
-
...options,
|
|
1085
|
-
disableJSONStringify: true,
|
|
1086
|
-
});
|
|
1087
|
-
}
|