@snowtop/ent 0.1.0-alpha1 → 0.1.0-alpha7
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/graphql/index.d.ts +1 -0
- package/graphql/index.js +3 -1
- package/graphql/mutations/union.d.ts +2 -0
- package/graphql/mutations/union.js +35 -0
- package/package.json +1 -1
- package/parse_schema/parse.d.ts +8 -2
- package/parse_schema/parse.js +28 -2
- package/schema/field.d.ts +1 -1
- package/schema/field.js +11 -3
- package/schema/index.d.ts +2 -0
- package/schema/index.js +2 -0
- package/schema/schema.d.ts +6 -3
- package/schema/schema.js +13 -0
- package/schema/struct_field.d.ts +17 -0
- package/schema/struct_field.js +102 -0
- package/schema/union_field.d.ts +23 -0
- package/schema/union_field.js +79 -0
package/graphql/index.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { GraphQLConnectionInterface } from "./builtins/connection";
|
|
|
8
8
|
export { GraphQLEdgeInterface } from "./builtins/edge";
|
|
9
9
|
export { NodeResolver, EntNodeResolver, registerResolver, clearResolvers, resolveID, nodeIDEncoder, mustDecodeIDFromGQLID, mustDecodeNullableIDFromGQLID, encodeGQLID, } from "./node_resolver";
|
|
10
10
|
export { convertFromGQLEnum, convertToGQLEnum } from "./enums";
|
|
11
|
+
export { transformUnionTypes } from "./mutations/union";
|
package/graphql/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertToGQLEnum = exports.convertFromGQLEnum = exports.encodeGQLID = exports.mustDecodeNullableIDFromGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = exports.GraphQLEdgeInterface = exports.GraphQLConnectionInterface = exports.GraphQLNodeInterface = exports.GraphQLConnectionType = exports.GraphQLEdgeType = exports.GraphQLEdgeConnection = exports.GraphQLPageInfo = exports.GraphQLTime = exports.gqlFileUpload = exports.GQLCapture = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlArg = exports.gqlField = void 0;
|
|
3
|
+
exports.transformUnionTypes = exports.convertToGQLEnum = exports.convertFromGQLEnum = exports.encodeGQLID = exports.mustDecodeNullableIDFromGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = exports.GraphQLEdgeInterface = exports.GraphQLConnectionInterface = exports.GraphQLNodeInterface = exports.GraphQLConnectionType = exports.GraphQLEdgeType = exports.GraphQLEdgeConnection = exports.GraphQLPageInfo = exports.GraphQLTime = exports.gqlFileUpload = exports.GQLCapture = exports.gqlConnection = exports.gqlContextType = exports.gqlMutation = exports.gqlQuery = exports.gqlObjectType = exports.gqlInputObjectType = exports.gqlArgType = exports.gqlArg = exports.gqlField = void 0;
|
|
4
4
|
var graphql_1 = require("./graphql");
|
|
5
5
|
Object.defineProperty(exports, "gqlField", { enumerable: true, get: function () { return graphql_1.gqlField; } });
|
|
6
6
|
Object.defineProperty(exports, "gqlArg", { enumerable: true, get: function () { return graphql_1.gqlArg; } });
|
|
@@ -40,3 +40,5 @@ Object.defineProperty(exports, "encodeGQLID", { enumerable: true, get: function
|
|
|
40
40
|
var enums_1 = require("./enums");
|
|
41
41
|
Object.defineProperty(exports, "convertFromGQLEnum", { enumerable: true, get: function () { return enums_1.convertFromGQLEnum; } });
|
|
42
42
|
Object.defineProperty(exports, "convertToGQLEnum", { enumerable: true, get: function () { return enums_1.convertToGQLEnum; } });
|
|
43
|
+
var union_1 = require("./mutations/union");
|
|
44
|
+
Object.defineProperty(exports, "transformUnionTypes", { enumerable: true, get: function () { return union_1.transformUnionTypes; } });
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformUnionTypes = void 0;
|
|
4
|
+
// this transforms an input for union types from graphql format to TS format
|
|
5
|
+
// in graphql, we represent it as UnionType = {foo: FooType, bar: BarType, baz: BazType}
|
|
6
|
+
// in TS, we repseent it as UnionType = FooType | BarType | BazType
|
|
7
|
+
// this takes an input, paths to unions and transforms them as needed
|
|
8
|
+
// only works on fields that are defined. depends on graphql to handle nullable/missing fields
|
|
9
|
+
function transformUnionTypes(input, pathsList) {
|
|
10
|
+
for (const paths of pathsList) {
|
|
11
|
+
const lastPath = paths[paths.length - 1];
|
|
12
|
+
let last = input;
|
|
13
|
+
for (const path of paths) {
|
|
14
|
+
let curr = last[path];
|
|
15
|
+
if (curr === undefined) {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
if (path === lastPath) {
|
|
19
|
+
let count = 0;
|
|
20
|
+
let lastKey = undefined;
|
|
21
|
+
for (const k in curr) {
|
|
22
|
+
count++;
|
|
23
|
+
lastKey = k;
|
|
24
|
+
}
|
|
25
|
+
if (count != 1) {
|
|
26
|
+
throw new Error(`can only only pass one key of union. passed ${count}`);
|
|
27
|
+
}
|
|
28
|
+
last[path] = curr[lastKey];
|
|
29
|
+
}
|
|
30
|
+
last = curr;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return input;
|
|
34
|
+
}
|
|
35
|
+
exports.transformUnionTypes = transformUnionTypes;
|
package/package.json
CHANGED
package/parse_schema/parse.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema, Field, AssocEdge, AssocEdgeGroup, Action } from "../schema";
|
|
1
|
+
import { Schema, Field, AssocEdge, AssocEdgeGroup, Action, Type } from "../schema";
|
|
2
2
|
import { ActionField } from "../schema/schema";
|
|
3
3
|
declare enum NullableResult {
|
|
4
4
|
CONTENTS = "contents",
|
|
@@ -32,12 +32,18 @@ interface ProcessedPattern {
|
|
|
32
32
|
assocEdges: ProcessedAssocEdge[];
|
|
33
33
|
fields: ProcessedField[];
|
|
34
34
|
}
|
|
35
|
-
declare type
|
|
35
|
+
declare type ProcessedType = Omit<Type, "subFields" | "listElemType" | "unionFields"> & {
|
|
36
|
+
subFields?: ProcessedField[];
|
|
37
|
+
listElemType?: ProcessedType;
|
|
38
|
+
unionFields?: ProcessedField[];
|
|
39
|
+
};
|
|
40
|
+
declare type ProcessedField = Omit<Field, "defaultValueOnEdit" | "defaultValueOnCreate" | "type"> & {
|
|
36
41
|
name: string;
|
|
37
42
|
hasDefaultValueOnCreate?: boolean;
|
|
38
43
|
hasDefaultValueOnEdit?: boolean;
|
|
39
44
|
patternName?: string;
|
|
40
45
|
derivedFields?: ProcessedField[];
|
|
46
|
+
type: ProcessedType;
|
|
41
47
|
};
|
|
42
48
|
interface patternsDict {
|
|
43
49
|
[key: string]: ProcessedPattern;
|
package/parse_schema/parse.js
CHANGED
|
@@ -3,8 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseSchema = void 0;
|
|
4
4
|
function processFields(src, patternName) {
|
|
5
5
|
const ret = [];
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
let m = {};
|
|
7
|
+
if (Array.isArray(src)) {
|
|
8
|
+
for (const field of src) {
|
|
9
|
+
const name = field.name;
|
|
10
|
+
if (!name) {
|
|
11
|
+
throw new Error(`name is required`);
|
|
12
|
+
}
|
|
13
|
+
m[name] = field;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
m = src;
|
|
18
|
+
}
|
|
19
|
+
for (const name in m) {
|
|
20
|
+
const field = m[name];
|
|
21
|
+
//@ts-ignore type and other changed fields with different type in ProcessedField vs Field
|
|
8
22
|
let f = { name, ...field };
|
|
9
23
|
f.hasDefaultValueOnCreate = field.defaultValueOnCreate != undefined;
|
|
10
24
|
f.hasDefaultValueOnEdit = field.defaultValueOnEdit != undefined;
|
|
@@ -35,6 +49,18 @@ function processFields(src, patternName) {
|
|
|
35
49
|
if (field.getDerivedFields) {
|
|
36
50
|
f.derivedFields = processFields(field.getDerivedFields(name));
|
|
37
51
|
}
|
|
52
|
+
if (field.type.subFields) {
|
|
53
|
+
f.type.subFields = processFields(field.type.subFields);
|
|
54
|
+
}
|
|
55
|
+
if (field.type.unionFields) {
|
|
56
|
+
f.type.unionFields = processFields(field.type.unionFields);
|
|
57
|
+
}
|
|
58
|
+
if (field.type.listElemType &&
|
|
59
|
+
field.type.listElemType.subFields &&
|
|
60
|
+
// check to avoid ts-ignore below. exists just for tsc
|
|
61
|
+
f.type.listElemType) {
|
|
62
|
+
f.type.listElemType.subFields = processFields(field.type.listElemType.subFields);
|
|
63
|
+
}
|
|
38
64
|
ret.push(f);
|
|
39
65
|
}
|
|
40
66
|
return ret;
|
package/schema/field.d.ts
CHANGED
|
@@ -146,7 +146,7 @@ export declare class ListField extends BaseField {
|
|
|
146
146
|
validate(validator: (val: any[]) => boolean): this;
|
|
147
147
|
valid(val: any): Promise<boolean>;
|
|
148
148
|
private postgresVal;
|
|
149
|
-
format(val: any): any;
|
|
149
|
+
format(val: any, nested?: boolean): any;
|
|
150
150
|
minLen(l: number): this;
|
|
151
151
|
maxLen(l: number): this;
|
|
152
152
|
length(l: number): this;
|
package/schema/field.js
CHANGED
|
@@ -597,13 +597,17 @@ class ListField extends BaseField {
|
|
|
597
597
|
}
|
|
598
598
|
return JSON.stringify(val);
|
|
599
599
|
}
|
|
600
|
-
format(val) {
|
|
600
|
+
format(val, nested) {
|
|
601
601
|
if (!Array.isArray(val)) {
|
|
602
602
|
throw new Error(`need an array to format`);
|
|
603
603
|
}
|
|
604
604
|
const elemDBType = this.type.listElemType.dbType;
|
|
605
605
|
const jsonType = elemDBType === "JSON" || elemDBType === "JSONB";
|
|
606
|
-
|
|
606
|
+
// postgres ish doesn't apply when nested
|
|
607
|
+
const postgres = !nested && db_1.default.getDialect() === db_1.Dialect.Postgres;
|
|
608
|
+
if (nested && !this.field.format) {
|
|
609
|
+
return val;
|
|
610
|
+
}
|
|
607
611
|
if (!postgres && !this.field.format) {
|
|
608
612
|
return JSON.stringify(val);
|
|
609
613
|
}
|
|
@@ -612,7 +616,7 @@ class ListField extends BaseField {
|
|
|
612
616
|
for (let i = 0; i < val.length; i++) {
|
|
613
617
|
let formatted = val[i];
|
|
614
618
|
if (this.field.format) {
|
|
615
|
-
formatted = this.field.format(val[i]);
|
|
619
|
+
formatted = this.field.format(val[i], nested);
|
|
616
620
|
}
|
|
617
621
|
// postgres supports arrays natively so we
|
|
618
622
|
// structure it in the expected format
|
|
@@ -629,6 +633,10 @@ class ListField extends BaseField {
|
|
|
629
633
|
if (postgres) {
|
|
630
634
|
return postgresRet + "}";
|
|
631
635
|
}
|
|
636
|
+
// don't JSON.stringify if nested
|
|
637
|
+
if (nested) {
|
|
638
|
+
return ret;
|
|
639
|
+
}
|
|
632
640
|
return JSON.stringify(ret);
|
|
633
641
|
}
|
|
634
642
|
minLen(l) {
|
package/schema/index.d.ts
CHANGED
|
@@ -4,3 +4,5 @@ export { Field, AssocEdge, AssocEdgeGroup, InverseAssocEdge, Edge, Pattern, DBTy
|
|
|
4
4
|
export { Timestamps, Node, BaseEntSchema, BaseEntSchemaWithTZ, } from "./base_schema";
|
|
5
5
|
export * from "./field";
|
|
6
6
|
export * from "./json_field";
|
|
7
|
+
export * from "./struct_field";
|
|
8
|
+
export * from "./union_field";
|
package/schema/index.js
CHANGED
|
@@ -26,3 +26,5 @@ Object.defineProperty(exports, "BaseEntSchema", { enumerable: true, get: functio
|
|
|
26
26
|
Object.defineProperty(exports, "BaseEntSchemaWithTZ", { enumerable: true, get: function () { return base_schema_1.BaseEntSchemaWithTZ; } });
|
|
27
27
|
__exportStar(require("./field"), exports);
|
|
28
28
|
__exportStar(require("./json_field"), exports);
|
|
29
|
+
__exportStar(require("./struct_field"), exports);
|
|
30
|
+
__exportStar(require("./union_field"), exports);
|
package/schema/schema.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare type FieldMap = {
|
|
|
4
4
|
[key: string]: Field;
|
|
5
5
|
};
|
|
6
6
|
export default interface Schema {
|
|
7
|
-
fields: FieldMap;
|
|
7
|
+
fields: FieldMap | Field[];
|
|
8
8
|
tableName?: string;
|
|
9
9
|
patterns?: Pattern[];
|
|
10
10
|
edges?: Edge[];
|
|
@@ -60,7 +60,7 @@ export interface AssocEdgeGroup {
|
|
|
60
60
|
export declare type Edge = AssocEdge;
|
|
61
61
|
export interface Pattern {
|
|
62
62
|
name: string;
|
|
63
|
-
fields: FieldMap;
|
|
63
|
+
fields: FieldMap | Field[];
|
|
64
64
|
edges?: Edge[];
|
|
65
65
|
}
|
|
66
66
|
export declare enum DBType {
|
|
@@ -97,6 +97,8 @@ export interface Type {
|
|
|
97
97
|
values?: string[];
|
|
98
98
|
enumMap?: EnumMap;
|
|
99
99
|
importType?: ImportType;
|
|
100
|
+
subFields?: FieldMap;
|
|
101
|
+
unionFields?: FieldMap;
|
|
100
102
|
}
|
|
101
103
|
export interface ForeignKey {
|
|
102
104
|
schema: string;
|
|
@@ -139,6 +141,7 @@ export interface FieldOptions {
|
|
|
139
141
|
derivedWhenEmbedded?: boolean;
|
|
140
142
|
polymorphic?: boolean | PolymorphicOptions;
|
|
141
143
|
getDerivedFields?(name: string): FieldMap;
|
|
144
|
+
[x: string]: any;
|
|
142
145
|
}
|
|
143
146
|
export interface PolymorphicOptions {
|
|
144
147
|
types?: string[];
|
|
@@ -148,7 +151,7 @@ export interface PolymorphicOptions {
|
|
|
148
151
|
export interface Field extends FieldOptions {
|
|
149
152
|
type: Type;
|
|
150
153
|
valid?(val: any): Promise<boolean> | boolean;
|
|
151
|
-
format?(val: any): any;
|
|
154
|
+
format?(val: any, nested?: boolean): any;
|
|
152
155
|
logValue(val: any): any;
|
|
153
156
|
}
|
|
154
157
|
export interface SchemaConstructor {
|
package/schema/schema.js
CHANGED
|
@@ -37,6 +37,19 @@ function getFields(value) {
|
|
|
37
37
|
schema = new value();
|
|
38
38
|
}
|
|
39
39
|
function addFields(fields) {
|
|
40
|
+
if (Array.isArray(fields)) {
|
|
41
|
+
for (const field of fields) {
|
|
42
|
+
const name = field.name;
|
|
43
|
+
if (!name) {
|
|
44
|
+
throw new Error(`name required`);
|
|
45
|
+
}
|
|
46
|
+
if (field.getDerivedFields !== undefined) {
|
|
47
|
+
addFields(field.getDerivedFields(name));
|
|
48
|
+
}
|
|
49
|
+
m.set(name, field);
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
40
53
|
for (const name in fields) {
|
|
41
54
|
const field = fields[name];
|
|
42
55
|
if (field.getDerivedFields !== undefined) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseField, ListField } from "./field";
|
|
2
|
+
import { FieldOptions, Field, Type, FieldMap } from "./schema";
|
|
3
|
+
export interface StructOptions extends FieldOptions {
|
|
4
|
+
tsType: string;
|
|
5
|
+
fields: FieldMap;
|
|
6
|
+
graphQLType?: string;
|
|
7
|
+
jsonNotJSONB?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class StructField extends BaseField implements Field {
|
|
10
|
+
private options;
|
|
11
|
+
type: Type;
|
|
12
|
+
constructor(options: StructOptions);
|
|
13
|
+
format(obj: any, nested?: boolean): string | Object;
|
|
14
|
+
valid(obj: any): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
export declare function StructType(options: StructOptions): StructField & StructOptions;
|
|
17
|
+
export declare function StructListType(options: StructOptions): ListField;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StructListType = exports.StructType = exports.StructField = void 0;
|
|
4
|
+
const field_1 = require("./field");
|
|
5
|
+
const schema_1 = require("./schema");
|
|
6
|
+
const camel_case_1 = require("camel-case");
|
|
7
|
+
class StructField extends field_1.BaseField {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super();
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.type = {
|
|
12
|
+
dbType: schema_1.DBType.JSONB,
|
|
13
|
+
};
|
|
14
|
+
this.type.subFields = options.fields;
|
|
15
|
+
this.type.type = options.tsType;
|
|
16
|
+
this.type.graphQLType = options.graphQLType || options.tsType;
|
|
17
|
+
if (options.jsonNotJSONB) {
|
|
18
|
+
this.type.dbType = schema_1.DBType.JSON;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// right now, we store things in the db in lowerCase format
|
|
22
|
+
// this will lead to issues if field changes.
|
|
23
|
+
// TODO: use storageKey and convert back...
|
|
24
|
+
format(obj, nested) {
|
|
25
|
+
if (!(obj instanceof Object)) {
|
|
26
|
+
throw new Error("valid was not called");
|
|
27
|
+
}
|
|
28
|
+
let ret = {};
|
|
29
|
+
for (const k in this.options.fields) {
|
|
30
|
+
// TODO more #510
|
|
31
|
+
let dbKey = (0, camel_case_1.camelCase)(k);
|
|
32
|
+
let val = obj[dbKey];
|
|
33
|
+
// for tests with snake_case
|
|
34
|
+
if (val === undefined && obj[k] !== undefined) {
|
|
35
|
+
val = obj[k];
|
|
36
|
+
dbKey = k;
|
|
37
|
+
}
|
|
38
|
+
if (val === undefined) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const field = this.options.fields[k];
|
|
42
|
+
if (field.format) {
|
|
43
|
+
// indicate nested so this isn't JSON stringified
|
|
44
|
+
ret[dbKey] = field.format(val, true);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
ret[dbKey] = val;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// don't json.stringify if nested
|
|
51
|
+
if (nested) {
|
|
52
|
+
return ret;
|
|
53
|
+
}
|
|
54
|
+
return JSON.stringify(ret);
|
|
55
|
+
}
|
|
56
|
+
async valid(obj) {
|
|
57
|
+
if (!(obj instanceof Object)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
let promises = [];
|
|
61
|
+
// TODO probably need to support optional fields...
|
|
62
|
+
let valid = true;
|
|
63
|
+
for (const k in this.options.fields) {
|
|
64
|
+
const field = this.options.fields[k];
|
|
65
|
+
// TODO more #510
|
|
66
|
+
let dbKey = (0, camel_case_1.camelCase)(k);
|
|
67
|
+
let val = obj[dbKey];
|
|
68
|
+
// for tests with snake_case
|
|
69
|
+
if (val === undefined && obj[k] !== undefined) {
|
|
70
|
+
val = obj[k];
|
|
71
|
+
dbKey = k;
|
|
72
|
+
}
|
|
73
|
+
if (val === undefined || val === null) {
|
|
74
|
+
// nullable, nothing to do here
|
|
75
|
+
if (field.nullable) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
valid = false;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (!field.valid) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
promises.push(field.valid(val));
|
|
85
|
+
}
|
|
86
|
+
if (!valid) {
|
|
87
|
+
return valid;
|
|
88
|
+
}
|
|
89
|
+
const ret = await Promise.all(promises);
|
|
90
|
+
return ret.every((v) => v);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.StructField = StructField;
|
|
94
|
+
function StructType(options) {
|
|
95
|
+
let result = new StructField(options);
|
|
96
|
+
return Object.assign(result, options);
|
|
97
|
+
}
|
|
98
|
+
exports.StructType = StructType;
|
|
99
|
+
function StructListType(options) {
|
|
100
|
+
return new field_1.ListField(StructType(options), options);
|
|
101
|
+
}
|
|
102
|
+
exports.StructListType = StructListType;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { StructField } from "./struct_field";
|
|
2
|
+
import { FieldOptions, Type } from "./schema";
|
|
3
|
+
import { BaseField, ListField } from "./field";
|
|
4
|
+
export declare type StructMap = {
|
|
5
|
+
[key: string]: StructField;
|
|
6
|
+
};
|
|
7
|
+
export interface UnionOptions extends FieldOptions {
|
|
8
|
+
tsType: string;
|
|
9
|
+
fields: StructMap;
|
|
10
|
+
graphQLType?: string;
|
|
11
|
+
jsonNotJSONB?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class UnionField extends BaseField implements FieldOptions {
|
|
14
|
+
private options;
|
|
15
|
+
type: Type;
|
|
16
|
+
m: Map<Object, string>;
|
|
17
|
+
constructor(options: UnionOptions);
|
|
18
|
+
format(obj: any): string | Object;
|
|
19
|
+
private validField;
|
|
20
|
+
valid(obj: any): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
export declare function UnionType(options: UnionOptions): UnionField & UnionOptions;
|
|
23
|
+
export declare function UnionListType(options: UnionOptions): ListField;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnionListType = exports.UnionType = exports.UnionField = void 0;
|
|
4
|
+
const schema_1 = require("./schema");
|
|
5
|
+
const field_1 = require("./field");
|
|
6
|
+
// used to know which key in the union is valid.
|
|
7
|
+
// maybe there's a better way of doing this eventually
|
|
8
|
+
const KEY = "___valid___key___";
|
|
9
|
+
class UnionField extends field_1.BaseField {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super();
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.type = {
|
|
14
|
+
dbType: schema_1.DBType.JSONB,
|
|
15
|
+
};
|
|
16
|
+
this.m = new Map();
|
|
17
|
+
this.type.unionFields = options.fields;
|
|
18
|
+
this.type.type = options.tsType;
|
|
19
|
+
this.type.graphQLType = options.graphQLType || options.tsType;
|
|
20
|
+
// TODO should throw if not nested?
|
|
21
|
+
if (options.jsonNotJSONB) {
|
|
22
|
+
this.type.dbType = schema_1.DBType.JSON;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
format(obj) {
|
|
26
|
+
if (!(obj instanceof Object)) {
|
|
27
|
+
throw new Error("valid was not called");
|
|
28
|
+
}
|
|
29
|
+
const k = obj[KEY];
|
|
30
|
+
if (k === undefined) {
|
|
31
|
+
throw new Error(`need to call valid first`);
|
|
32
|
+
}
|
|
33
|
+
// now delete it since we don't need it anymore
|
|
34
|
+
delete obj[KEY];
|
|
35
|
+
const field = this.options.fields[k];
|
|
36
|
+
// always nested for now so pass through
|
|
37
|
+
return field.format(obj, true);
|
|
38
|
+
}
|
|
39
|
+
async validField(k, f, obj) {
|
|
40
|
+
const valid = await f.valid(obj);
|
|
41
|
+
return {
|
|
42
|
+
valid,
|
|
43
|
+
key: k,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async valid(obj) {
|
|
47
|
+
if (!(obj instanceof Object)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
let promises = [];
|
|
51
|
+
for (const k in this.options.fields) {
|
|
52
|
+
const field = this.options.fields[k];
|
|
53
|
+
promises.push(this.validField(k, field, obj));
|
|
54
|
+
}
|
|
55
|
+
let lastKey;
|
|
56
|
+
let validCt = 0;
|
|
57
|
+
const ret = await Promise.all(promises);
|
|
58
|
+
for (const v of ret) {
|
|
59
|
+
if (v.valid) {
|
|
60
|
+
validCt++;
|
|
61
|
+
lastKey = v.key;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (lastKey !== undefined) {
|
|
65
|
+
obj[KEY] = lastKey;
|
|
66
|
+
}
|
|
67
|
+
return validCt == 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.UnionField = UnionField;
|
|
71
|
+
function UnionType(options) {
|
|
72
|
+
let result = new UnionField(options);
|
|
73
|
+
return Object.assign(result, options);
|
|
74
|
+
}
|
|
75
|
+
exports.UnionType = UnionType;
|
|
76
|
+
function UnionListType(options) {
|
|
77
|
+
return new field_1.ListField(UnionType(options), options);
|
|
78
|
+
}
|
|
79
|
+
exports.UnionListType = UnionListType;
|