@snowtop/ent 0.0.32-alpha.5 → 0.1.0-alpha

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.
@@ -14,6 +14,7 @@ export interface Builder<T extends Ent> {
14
14
  build(): Promise<Changeset<T>>;
15
15
  operation: WriteOperation;
16
16
  editedEnt?(): Promise<T | null>;
17
+ nodeType: string;
17
18
  }
18
19
  export interface Executor extends Iterable<DataOperation>, Iterator<DataOperation> {
19
20
  placeholderID: ID;
@@ -31,24 +32,24 @@ export interface Changeset<T extends Ent> {
31
32
  dependencies?: Map<ID, Builder<Ent>>;
32
33
  }
33
34
  export declare type TriggerReturn = void | Promise<Changeset<Ent> | void | (Changeset<Ent> | void)[]> | Promise<Changeset<Ent>>[];
34
- export interface Trigger<T extends Ent> {
35
- changeset(builder: Builder<T>, input: Data): TriggerReturn;
35
+ export interface Trigger<TBuilder extends Builder<Ent>, TData extends Data> {
36
+ changeset(builder: TBuilder, input: TData): TriggerReturn;
36
37
  }
37
- export interface Observer<T extends Ent> {
38
- observe(builder: Builder<T>, input: Data): void | Promise<void>;
38
+ export interface Observer<TBuilder extends Builder<Ent>, TData extends Data> {
39
+ observe(builder: TBuilder, input: TData): void | Promise<void>;
39
40
  }
40
- export interface Validator<T extends Ent> {
41
- validate(builder: Builder<T>, input: Data): Promise<void> | void;
41
+ export interface Validator<TBuilder extends Builder<Ent>, TData extends Data> {
42
+ validate(builder: TBuilder, input: TData): Promise<void> | void;
42
43
  }
43
- export interface Action<T extends Ent> {
44
+ export interface Action<TEnt extends Ent, TBuilder extends Builder<TEnt>, TData extends Data> {
44
45
  readonly viewer: Viewer;
45
- changeset(): Promise<Changeset<T>>;
46
- builder: Builder<T>;
47
- getPrivacyPolicy(): PrivacyPolicy;
48
- triggers?: Trigger<T>[];
49
- observers?: Observer<T>[];
50
- validators?: Validator<T>[];
51
- getInput(): Data;
46
+ changeset(): Promise<Changeset<TEnt>>;
47
+ builder: TBuilder;
48
+ getPrivacyPolicy(): PrivacyPolicy<TEnt>;
49
+ triggers?: Trigger<TBuilder, TData>[];
50
+ observers?: Observer<TBuilder, TData>[];
51
+ validators?: Validator<TBuilder, TData>[];
52
+ getInput(): TData;
52
53
  valid(): Promise<boolean>;
53
54
  validX(): Promise<void>;
54
55
  viewerForEntLoad?(data: Data): Viewer | Promise<Viewer>;
@@ -1,8 +1,8 @@
1
1
  import { Viewer, Ent, Data } from "../core/base";
2
2
  import { Action, WriteOperation, Builder, Trigger, Observer, Changeset, Validator } from "./action";
3
- export interface ActionOptions<T extends Ent> {
3
+ export interface ActionOptions<T extends Ent, TData extends Data> {
4
4
  existingEnt?: T | null;
5
- input?: {};
5
+ input?: TData;
6
6
  operation?: WriteOperation;
7
7
  }
8
8
  interface EntBuilder<T extends Ent> extends Builder<T> {
@@ -13,28 +13,28 @@ interface EntBuilder<T extends Ent> extends Builder<T> {
13
13
  editedEnt(): Promise<T | null>;
14
14
  editedEntX(): Promise<T>;
15
15
  }
16
- export declare class BaseAction<T extends Ent> implements Action<T> {
16
+ export declare class BaseAction<TEnt extends Ent, TData extends Data> implements Action<TEnt, EntBuilder<TEnt>, TData> {
17
17
  viewer: Viewer;
18
- builderCtr: BuilderConstructor<T>;
19
- builder: EntBuilder<T>;
18
+ builderCtr: BuilderConstructor<TEnt, TData>;
19
+ builder: EntBuilder<TEnt>;
20
20
  private input;
21
- triggers: Trigger<Ent>[];
22
- observers: Observer<Ent>[];
23
- validators: Validator<Ent>[];
24
- getPrivacyPolicy(): import("../core/base").PrivacyPolicy;
25
- constructor(viewer: Viewer, builderCtr: BuilderConstructor<T>, options?: ActionOptions<T> | null);
26
- static createBuilder<T extends Ent>(viewer: Viewer, builderCtr: BuilderConstructor<T>, options?: ActionOptions<T> | null): Builder<T>;
27
- static bulkAction<T extends Ent>(ent: T, builderCtr: BuilderConstructor<T>, ...actions: Action<Ent>[]): BaseAction<T>;
28
- changeset(): Promise<Changeset<T>>;
21
+ triggers: Trigger<EntBuilder<TEnt>, TData>[];
22
+ observers: Observer<EntBuilder<TEnt>, TData>[];
23
+ validators: Validator<EntBuilder<TEnt>, TData>[];
24
+ getPrivacyPolicy(): import("../core/base").PrivacyPolicy<Ent>;
25
+ constructor(viewer: Viewer, builderCtr: BuilderConstructor<TEnt, TData>, options?: ActionOptions<TEnt, TData> | null);
26
+ static createBuilder<TEnt extends Ent, TData extends Data>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt, TData>, options?: ActionOptions<TEnt, TData> | null): Builder<TEnt>;
27
+ static bulkAction<TEnt extends Ent, TData extends Data>(ent: TEnt, builderCtr: BuilderConstructor<TEnt, TData>, ...actions: Action<Ent, Builder<Ent>, Data>[]): BaseAction<TEnt, TData>;
28
+ changeset(): Promise<Changeset<TEnt>>;
29
29
  valid(): Promise<boolean>;
30
30
  validX(): Promise<void>;
31
- save(): Promise<T | null>;
32
- saveX(): Promise<T>;
33
- getInput(): {};
31
+ save(): Promise<TEnt | null>;
32
+ saveX(): Promise<TEnt>;
33
+ getInput(): TData;
34
34
  }
35
- interface BuilderConstructor<T extends Ent> {
36
- new (viewer: Viewer, operation: WriteOperation, action: Action<T>, existingEnt?: T | undefined): EntBuilder<T>;
35
+ interface BuilderConstructor<TEnt extends Ent, TData extends Data> {
36
+ new (viewer: Viewer, operation: WriteOperation, action: Action<TEnt, EntBuilder<TEnt>, TData>, existingEnt?: TEnt | undefined): EntBuilder<TEnt>;
37
37
  }
38
- export declare function updateRawObject<TEnt extends Ent, TInput extends Data>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt>, existingEnt: TEnt, input: TInput): Promise<TEnt>;
39
- export declare function getSimpleEditAction<TEnt extends Ent, TInput extends Data>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt>, existingEnt: TEnt, input: TInput): Action<TEnt>;
38
+ export declare function updateRawObject<TEnt extends Ent, TInput extends Data>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt, TInput>, existingEnt: TEnt, input: TInput): Promise<TEnt>;
39
+ export declare function getSimpleEditAction<TEnt extends Ent, TInput extends Data>(viewer: Viewer, builderCtr: BuilderConstructor<TEnt, TInput>, existingEnt: TEnt, input: TInput): Action<TEnt, Builder<TEnt>, TInput>;
40
40
  export {};
@@ -37,7 +37,7 @@ class BaseAction {
37
37
  });
38
38
  action.triggers = [
39
39
  {
40
- changeset: (builder, _input) => {
40
+ changeset: () => {
41
41
  return actions.map((action) => action.changeset());
42
42
  },
43
43
  },
@@ -3,14 +3,14 @@ import { AssocEdgeInputOptions, DataOperation } from "../core/ent";
3
3
  import { SchemaInputType } from "../schema/schema";
4
4
  import { Changeset, Executor } from "../action/action";
5
5
  import { WriteOperation, Builder, Action } from "../action";
6
- export interface OrchestratorOptions<T extends Ent, TData extends Data> {
6
+ export interface OrchestratorOptions<TEnt extends Ent, TData extends Data> {
7
7
  viewer: Viewer;
8
8
  operation: WriteOperation;
9
9
  tableName: string;
10
- loaderOptions: LoadEntOptions<T>;
10
+ loaderOptions: LoadEntOptions<TEnt>;
11
11
  key: string;
12
- builder: Builder<T>;
13
- action?: Action<T>;
12
+ builder: Builder<TEnt>;
13
+ action?: Action<TEnt, Builder<TEnt>, TData>;
14
14
  schema: SchemaInputType;
15
15
  editedFields(): Map<string, any>;
16
16
  updateInput?: (data: TData) => void;
@@ -28,7 +28,7 @@ export declare enum edgeDirection {
28
28
  inboundEdge = 0,
29
29
  outboundEdge = 1
30
30
  }
31
- export declare class Orchestrator<T extends Ent> {
31
+ export declare class Orchestrator<TEnt extends Ent, TData extends Data> {
32
32
  private options;
33
33
  private edgeSet;
34
34
  private edges;
@@ -41,7 +41,7 @@ export declare class Orchestrator<T extends Ent> {
41
41
  viewer: Viewer;
42
42
  private defaultFieldsByFieldName;
43
43
  private defaultFieldsByTSName;
44
- constructor(options: OrchestratorOptions<T, Data>);
44
+ constructor(options: OrchestratorOptions<TEnt, TData>);
45
45
  private addEdge;
46
46
  addInboundEdge<T2 extends Ent>(id1: ID | Builder<T2>, edgeType: string, nodeType: string, options?: AssocEdgeInputOptions): void;
47
47
  addOutboundEdge<T2 extends Ent>(id2: ID | Builder<T2>, edgeType: string, nodeType: string, options?: AssocEdgeInputOptions): void;
@@ -64,11 +64,11 @@ export declare class Orchestrator<T extends Ent> {
64
64
  private formatAndValidateFields;
65
65
  valid(): Promise<boolean>;
66
66
  validX(): Promise<void>;
67
- build(): Promise<EntChangeset<T>>;
67
+ build(): Promise<EntChangeset<TEnt>>;
68
68
  private viewerForEntLoad;
69
69
  returnedRow(): Promise<Data | null>;
70
- editedEnt(): Promise<T | null>;
71
- editedEntX(): Promise<T>;
70
+ editedEnt(): Promise<TEnt | null>;
71
+ editedEntX(): Promise<TEnt>;
72
72
  }
73
73
  export declare class EntChangeset<T extends Ent> implements Changeset<T> {
74
74
  viewer: Viewer;
package/core/base.d.ts CHANGED
@@ -43,7 +43,7 @@ export interface Viewer {
43
43
  export interface Ent {
44
44
  id: ID;
45
45
  viewer: Viewer;
46
- privacyPolicy: PrivacyPolicy;
46
+ privacyPolicy: PrivacyPolicy<this>;
47
47
  nodeType: string;
48
48
  }
49
49
  export declare type Data = {
@@ -92,6 +92,12 @@ export interface LoadEntOptions<T extends Ent> extends LoadableEntOptions<T>, Se
92
92
  export interface LoadCustomEntOptions<T extends Ent> extends SelectBaseDataOptions {
93
93
  ent: EntConstructor<T>;
94
94
  }
95
+ export interface LoaderInfo {
96
+ tableName: string;
97
+ fields: string[];
98
+ nodeType: string;
99
+ loaderFactory: LoaderFactory<any, Data | null>;
100
+ }
95
101
  export interface EditEntOptions<T extends Ent> extends LoadableEntOptions<T>, EditRowOptions {
96
102
  }
97
103
  declare enum privacyResult {
@@ -104,17 +110,17 @@ export interface PrivacyResult {
104
110
  error?: PrivacyError;
105
111
  }
106
112
  export interface PrivacyError extends Error {
107
- privacyPolicy: PrivacyPolicy;
113
+ privacyPolicy: PrivacyPolicy<Ent>;
108
114
  ent?: Ent;
109
115
  }
110
116
  export declare function Allow(): PrivacyResult;
111
117
  export declare function Skip(): PrivacyResult;
112
118
  export declare function Deny(): PrivacyResult;
113
119
  export declare function DenyWithReason(e: PrivacyError): PrivacyResult;
114
- export interface PrivacyPolicyRule {
115
- apply(v: Viewer, ent?: Ent): Promise<PrivacyResult>;
120
+ export interface PrivacyPolicyRule<TEnt extends Ent = Ent> {
121
+ apply(v: Viewer, ent?: TEnt): Promise<PrivacyResult>;
116
122
  }
117
- export interface PrivacyPolicy {
118
- rules: PrivacyPolicyRule[];
123
+ export interface PrivacyPolicy<TEnt extends Ent = Ent> {
124
+ rules: PrivacyPolicyRule<TEnt>[];
119
125
  }
120
126
  export {};
package/core/ent.d.ts CHANGED
@@ -10,7 +10,8 @@ export declare function loadEntX<T extends Ent>(viewer: Viewer, id: ID, options:
10
10
  export declare function loadEntXViaKey<T extends Ent>(viewer: Viewer, key: any, options: LoadEntOptions<T>): Promise<T>;
11
11
  export declare function loadEntFromClause<T extends Ent>(viewer: Viewer, options: LoadEntOptions<T>, clause: clause.Clause): Promise<T | null>;
12
12
  export declare function loadEntXFromClause<T extends Ent>(viewer: Viewer, options: LoadEntOptions<T>, clause: clause.Clause): Promise<T>;
13
- export declare function loadEnts<T extends Ent>(viewer: Viewer, options: LoadEntOptions<T>, ...ids: ID[]): Promise<T[]>;
13
+ export declare function loadEnts<T extends Ent>(viewer: Viewer, options: LoadEntOptions<T>, ...ids: ID[]): Promise<Map<ID, T>>;
14
+ export declare function loadEntsList<T extends Ent>(viewer: Viewer, options: LoadEntOptions<T>, ...ids: ID[]): Promise<T[]>;
14
15
  export declare function loadEntsFromClause<T extends Ent>(viewer: Viewer, clause: clause.Clause, options: LoadEntOptions<T>): Promise<Map<ID, T>>;
15
16
  export declare function loadCustomEnts<T extends Ent>(viewer: Viewer, options: LoadCustomEntOptions<T>, query: CustomQuery): Promise<T[]>;
16
17
  interface rawQueryOptions {
package/core/ent.js CHANGED
@@ -22,7 +22,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.getEdgeTypeInGroup = exports.applyPrivacyPolicyForRows = exports.applyPrivacyPolicyForRowX = exports.applyPrivacyPolicyForRow = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadCustomEdges = exports.loadEdges = exports.defaultEdgeQueryOptions = exports.DefaultLimit = exports.loadEdgeDatas = exports.loadEdgeData = exports.assocEdgeLoader = exports.AssocEdgeData = exports.getCursor = exports.AssocEdge = exports.DeleteNodeOperation = exports.deleteRowsSync = exports.deleteRows = exports.editRowSync = exports.editRow = exports.buildUpdateQuery = exports.createRowSync = exports.createRow = exports.buildInsertQuery = exports.EdgeOperation = exports.EditNodeOperation = exports.buildGroupQuery = exports.buildQuery = exports.loadRows = exports.performRawQuery = exports.loadRow = exports.loadRowX = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
25
+ exports.applyPrivacyPolicyForRows = exports.applyPrivacyPolicyForRowX = exports.applyPrivacyPolicyForRow = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadCustomEdges = exports.loadEdges = exports.defaultEdgeQueryOptions = exports.DefaultLimit = exports.loadEdgeDatas = exports.loadEdgeData = exports.assocEdgeLoader = exports.AssocEdgeData = exports.getCursor = exports.AssocEdge = exports.DeleteNodeOperation = exports.deleteRowsSync = exports.deleteRows = exports.editRowSync = exports.editRow = exports.buildUpdateQuery = exports.createRowSync = exports.createRow = exports.buildInsertQuery = exports.EdgeOperation = exports.EditNodeOperation = exports.buildGroupQuery = exports.buildQuery = exports.loadRows = exports.performRawQuery = exports.loadRow = exports.loadRowX = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadCustomData = exports.loadCustomEnts = exports.loadEntsFromClause = exports.loadEntsList = exports.loadEnts = exports.loadEntXFromClause = exports.loadEntFromClause = exports.loadEntXViaKey = exports.loadEntX = exports.loadEntViaKey = exports.loadEnt = void 0;
26
+ exports.getEdgeTypeInGroup = void 0;
26
27
  const db_1 = __importStar(require("./db"));
27
28
  const privacy_1 = require("./privacy");
28
29
  const clause = __importStar(require("./clause"));
@@ -145,7 +146,7 @@ async function loadEntXFromClause(viewer, options, clause) {
145
146
  exports.loadEntXFromClause = loadEntXFromClause;
146
147
  async function loadEnts(viewer, options, ...ids) {
147
148
  if (!ids.length) {
148
- return [];
149
+ return new Map();
149
150
  }
150
151
  let loaded = false;
151
152
  let rows = [];
@@ -175,12 +176,16 @@ async function loadEnts(viewer, options, ...ids) {
175
176
  // this is always "id" if not using an ObjectLoaderFactory
176
177
  clause.In("id", ...ids), options);
177
178
  }
179
+ return m;
178
180
  // TODO do we want to change this to be a map not a list so that it's easy to check for existence?
179
181
  // TODO eventually this should be doing a cache then db queyr and maybe depend on dataloader to get all the results at once
180
- // we need to get the result and re-sort... because the raw db access doesn't guarantee it in same order
181
- // apparently
182
- // let m = await loadEntsFromClause(viewer, clause.In("id", ...ids), options);
183
- let result = [];
182
+ }
183
+ exports.loadEnts = loadEnts;
184
+ // calls loadEnts and returns the results sorted in the order they were passed in
185
+ // useful for EntQuery and other paths where the order matters
186
+ async function loadEntsList(viewer, options, ...ids) {
187
+ const m = await loadEnts(viewer, options, ...ids);
188
+ const result = [];
184
189
  ids.forEach((id) => {
185
190
  let ent = m.get(id);
186
191
  if (ent) {
@@ -189,7 +194,7 @@ async function loadEnts(viewer, options, ...ids) {
189
194
  });
190
195
  return result;
191
196
  }
192
- exports.loadEnts = loadEnts;
197
+ exports.loadEntsList = loadEntsList;
193
198
  // we return a map here so that any sorting for queries that exist
194
199
  // can be done in O(N) time
195
200
  async function loadEntsFromClause(viewer, clause, options) {
@@ -1133,7 +1138,7 @@ async function loadNodesByEdge(viewer, id1, edgeType, options) {
1133
1138
  });
1134
1139
  // extract id2s
1135
1140
  const ids = rows.map((row) => row.id2);
1136
- return loadEnts(viewer, options, ...ids);
1141
+ return loadEntsList(viewer, options, ...ids);
1137
1142
  }
1138
1143
  exports.loadNodesByEdge = loadNodesByEdge;
1139
1144
  async function applyPrivacyPolicyForRow(viewer, options, row) {
@@ -73,7 +73,7 @@ class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
73
73
  }
74
74
  let promises = [];
75
75
  for (const [_, value] of m) {
76
- promises.push((0, ent_1.loadEnts)(this.viewer, value.options, ...value.ids));
76
+ promises.push((0, ent_1.loadEntsList)(this.viewer, value.options, ...value.ids));
77
77
  }
78
78
  const entss = await Promise.all(promises);
79
79
  const r = [];
@@ -83,7 +83,7 @@ class AssocEdgeQueryBase extends query_1.BaseEdgeQuery {
83
83
  return r;
84
84
  }
85
85
  const ids = edges.map((edge) => edge.id2);
86
- return await (0, ent_1.loadEnts)(this.viewer, this.options, ...ids);
86
+ return (0, ent_1.loadEntsList)(this.viewer, this.options, ...ids);
87
87
  }
88
88
  dataToID(edge) {
89
89
  return edge.id2;
@@ -41,7 +41,7 @@ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends E
41
41
  private idMap;
42
42
  private idsToFetch;
43
43
  constructor(viewer: Viewer, sortCol: string);
44
- getPrivacyPolicy(): PrivacyPolicy;
44
+ getPrivacyPolicy(): PrivacyPolicy<Ent>;
45
45
  abstract sourceEnt(id: ID): Promise<Ent | null>;
46
46
  first(n: number, after?: string): this;
47
47
  last(n: number, before?: string): this;
@@ -6,5 +6,5 @@ export { GraphQLEdgeType, GraphQLConnectionType, } from "./query/connection_type
6
6
  export { GraphQLNodeInterface } from "./builtins/node";
7
7
  export { GraphQLConnectionInterface } from "./builtins/connection";
8
8
  export { GraphQLEdgeInterface } from "./builtins/edge";
9
- export { NodeResolver, EntNodeResolver, registerResolver, clearResolvers, resolveID, nodeIDEncoder, mustDecodeIDFromGQLID, encodeGQLID, } from "./node_resolver";
9
+ export { NodeResolver, EntNodeResolver, registerResolver, clearResolvers, resolveID, nodeIDEncoder, mustDecodeIDFromGQLID, mustDecodeNullableIDFromGQLID, encodeGQLID, } from "./node_resolver";
10
10
  export { convertFromGQLEnum, convertToGQLEnum } from "./enums";
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.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.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; } });
@@ -35,6 +35,7 @@ Object.defineProperty(exports, "clearResolvers", { enumerable: true, get: functi
35
35
  Object.defineProperty(exports, "resolveID", { enumerable: true, get: function () { return node_resolver_1.resolveID; } });
36
36
  Object.defineProperty(exports, "nodeIDEncoder", { enumerable: true, get: function () { return node_resolver_1.nodeIDEncoder; } });
37
37
  Object.defineProperty(exports, "mustDecodeIDFromGQLID", { enumerable: true, get: function () { return node_resolver_1.mustDecodeIDFromGQLID; } });
38
+ Object.defineProperty(exports, "mustDecodeNullableIDFromGQLID", { enumerable: true, get: function () { return node_resolver_1.mustDecodeNullableIDFromGQLID; } });
38
39
  Object.defineProperty(exports, "encodeGQLID", { enumerable: true, get: function () { return node_resolver_1.encodeGQLID; } });
39
40
  var enums_1 = require("./enums");
40
41
  Object.defineProperty(exports, "convertFromGQLEnum", { enumerable: true, get: function () { return enums_1.convertFromGQLEnum; } });
@@ -24,5 +24,6 @@ export declare function clearResolvers(): Promise<void>;
24
24
  export declare function resolveID(viewer: Viewer, id: string): Promise<Node | null>;
25
25
  export declare const nodeIDEncoder: GraphQLFieldResolver<Ent, {}>;
26
26
  export declare function mustDecodeIDFromGQLID(id: string): ID;
27
+ export declare function mustDecodeNullableIDFromGQLID(id: string | null | undefined): any;
27
28
  export declare function encodeGQLID(node: Ent): string;
28
29
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encodeGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = void 0;
3
+ exports.encodeGQLID = exports.mustDecodeNullableIDFromGQLID = exports.mustDecodeIDFromGQLID = exports.nodeIDEncoder = exports.resolveID = exports.clearResolvers = exports.registerResolver = exports.EntNodeResolver = void 0;
4
4
  class EntNodeResolver {
5
5
  constructor(loader) {
6
6
  this.loader = loader;
@@ -76,6 +76,19 @@ function mustDecodeIDFromGQLID(id) {
76
76
  return decoded;
77
77
  }
78
78
  exports.mustDecodeIDFromGQLID = mustDecodeIDFromGQLID;
79
+ // TODO get the right (non-any) return type here. may need to change codegen to do the right thing here
80
+ function mustDecodeNullableIDFromGQLID(id) {
81
+ // support undefined because fields in action
82
+ if (id === null || id === undefined) {
83
+ return id;
84
+ }
85
+ const decoded = EntNodeResolver.decode(id);
86
+ if (!decoded) {
87
+ throw new Error(`wasn't able to decode invalid ${id}`);
88
+ }
89
+ return decoded;
90
+ }
91
+ exports.mustDecodeNullableIDFromGQLID = mustDecodeNullableIDFromGQLID;
79
92
  // This takes an ent and returns the graphql id
80
93
  function encodeGQLID(node) {
81
94
  // let's do 3 parts. we take the "node" prefix
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.0.32-alpha.5",
3
+ "version": "0.1.0-alpha",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -1,4 +1,4 @@
1
- import { Schema, AssocEdge, AssocEdgeGroup, Action } from "../schema";
1
+ import { Schema, Field, AssocEdge, AssocEdgeGroup, Action } from "../schema";
2
2
  import { ActionField } from "../schema/schema";
3
3
  declare enum NullableResult {
4
4
  CONTENTS = "contents",
@@ -12,10 +12,11 @@ declare type ProcessedAssocEdge = Omit<AssocEdge, "actionOnlyFields" | "edgeActi
12
12
  patternName?: string;
13
13
  edgeActions?: OutputAction[];
14
14
  };
15
- declare type ProcessedSchema = Omit<Schema, "edges" | "actions" | "edgeGroups"> & {
15
+ declare type ProcessedSchema = Omit<Schema, "edges" | "actions" | "edgeGroups" | "fields"> & {
16
16
  actions: OutputAction[];
17
17
  assocEdges: ProcessedAssocEdge[];
18
18
  assocEdgeGroups: ProcessedAssocEdgeGroup[];
19
+ fields: ProcessedField[];
19
20
  };
20
21
  declare type ProcessedAssocEdgeGroup = Omit<AssocEdgeGroup, "edgeAction"> & {
21
22
  edgeAction?: OutputAction;
@@ -29,7 +30,13 @@ interface schemasDict {
29
30
  interface ProcessedPattern {
30
31
  name: string;
31
32
  assocEdges: ProcessedAssocEdge[];
33
+ fields: ProcessedField[];
32
34
  }
35
+ declare type ProcessedField = Omit<Field, "defaultValueOnEdit" | "defaultValueOnCreate"> & {
36
+ hasDefaultValueOnCreate?: boolean;
37
+ hasDefaultValueOnEdit?: boolean;
38
+ patternName?: string;
39
+ };
33
40
  interface patternsDict {
34
41
  [key: string]: ProcessedPattern;
35
42
  }
@@ -1,19 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseSchema = void 0;
4
- function processFields(processedSchema, src) {
4
+ function processFields(src, patternName) {
5
+ const ret = [];
5
6
  for (const field of src) {
6
7
  let f = { ...field };
7
- f["hasDefaultValueOnCreate"] = field.defaultValueOnCreate != undefined;
8
- f["hasDefaultValueOnEdit"] = field.defaultValueOnEdit != undefined;
8
+ f.hasDefaultValueOnCreate = field.defaultValueOnCreate != undefined;
9
+ f.hasDefaultValueOnEdit = field.defaultValueOnEdit != undefined;
9
10
  if (field.polymorphic) {
10
11
  // convert boolean into object
11
12
  // we keep boolean as an option to keep API simple
12
13
  if (typeof field.polymorphic === "boolean") {
13
- f["polymorphic"] = {};
14
+ f.polymorphic = {};
14
15
  }
15
16
  else {
16
- f["polymorphic"] = field.polymorphic;
17
+ f.polymorphic = field.polymorphic;
17
18
  }
18
19
  }
19
20
  // convert string to object to make API consumed by go simple
@@ -24,16 +25,22 @@ function processFields(processedSchema, src) {
24
25
  };
25
26
  }
26
27
  }
27
- processedSchema.fields.push(f);
28
+ if (patternName) {
29
+ f.patternName = patternName;
30
+ }
31
+ ret.push(f);
28
32
  }
33
+ return ret;
29
34
  }
30
- function processEdges(dst, src, patternName) {
35
+ function processEdges(src, patternName) {
36
+ const ret = [];
31
37
  for (const edge of src) {
32
38
  let edge2 = { ...edge };
33
39
  edge2.edgeActions = edge.edgeActions?.map((action) => processAction(action));
34
40
  edge2.patternName = patternName;
35
- dst.push(edge2);
41
+ ret.push(edge2);
36
42
  }
43
+ return ret;
37
44
  }
38
45
  function processEdgeGroups(processedSchema, edgeGroups) {
39
46
  // array-ify this
@@ -49,26 +56,26 @@ function processEdgeGroups(processedSchema, edgeGroups) {
49
56
  }
50
57
  }
51
58
  function processPattern(patterns, pattern, processedSchema) {
52
- // TODO kill
53
- let name = pattern.name || "node";
59
+ const name = pattern.name;
60
+ const fields = processFields(pattern.fields, pattern.name);
61
+ processedSchema.fields.push(...fields);
62
+ if (pattern.edges) {
63
+ const edges = processEdges(pattern.edges, pattern.name);
64
+ processedSchema.assocEdges.push(...edges);
65
+ }
54
66
  if (patterns[name] === undefined) {
55
- const edges = [];
56
- if (pattern.edges) {
57
- processEdges(edges, pattern.edges);
58
- }
67
+ // intentionally processing separately and not passing pattern.name
68
+ const edges = processEdges(pattern.edges || []);
59
69
  patterns[name] = {
60
70
  name: pattern.name,
61
71
  assocEdges: edges,
72
+ fields: fields,
62
73
  };
63
74
  }
64
75
  else {
65
76
  // TODO ideally we want to make sure that different patterns don't have the same name
66
77
  // can't do a deepEqual check because function calls and therefore different instances in fields
67
78
  }
68
- processFields(processedSchema, pattern.fields);
69
- if (pattern.edges) {
70
- processEdges(processedSchema.assocEdges, pattern.edges, pattern.name);
71
- }
72
79
  }
73
80
  var NullableResult;
74
81
  (function (NullableResult) {
@@ -133,9 +140,11 @@ function parseSchema(potentialSchemas) {
133
140
  processPattern(patterns, pattern, processedSchema);
134
141
  }
135
142
  }
136
- processFields(processedSchema, schema.fields);
143
+ const fields = processFields(schema.fields);
144
+ processedSchema.fields.push(...fields);
137
145
  if (schema.edges) {
138
- processEdges(processedSchema.assocEdges, schema.edges);
146
+ const edges = processEdges(schema.edges);
147
+ processedSchema.assocEdges.push(...edges);
139
148
  }
140
149
  if (schema.edgeGroups) {
141
150
  processEdgeGroups(processedSchema, schema.edgeGroups);
package/schema/field.d.ts CHANGED
@@ -144,7 +144,7 @@ export declare class ListField extends BaseField {
144
144
  private validators;
145
145
  constructor(field: Field, options: FieldOptions);
146
146
  validate(validator: (val: any[]) => boolean): this;
147
- valid(val: any): boolean;
147
+ valid(val: any): Promise<boolean>;
148
148
  private postgresVal;
149
149
  format(val: any): any;
150
150
  minLen(l: number): this;
package/schema/field.js CHANGED
@@ -22,9 +22,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  exports.UUIDListType = exports.EnumListType = exports.DateListType = exports.TimetzListType = exports.TimeListType = exports.TimestamptzListType = exports.TimestampListType = exports.BooleanListType = exports.BigIntegerListType = exports.FloatListType = exports.IntegerListType = exports.IntListType = exports.StringListType = exports.ListField = exports.EnumType = exports.EnumField = exports.DateType = exports.DateField = exports.TimetzType = exports.TimeType = exports.TimeField = exports.leftPad = exports.TimestamptzType = exports.TimestampType = exports.TimestampField = exports.StringType = exports.StringField = exports.BooleanType = exports.BooleanField = exports.FloatType = exports.FloatField = exports.BigIntegerType = exports.BigIntegerField = exports.IntegerType = exports.IntegerField = exports.UUIDType = exports.UUIDField = exports.BaseField = void 0;
23
23
  const luxon_1 = require("luxon");
24
24
  const snake_case_1 = require("snake-case");
25
- const camel_case_1 = require("camel-case");
26
25
  const db_1 = __importStar(require("../core/db"));
27
26
  const schema_1 = require("./schema");
27
+ const util_1 = require("util");
28
28
  class BaseField {
29
29
  logValue(val) {
30
30
  if (this.sensitive) {
@@ -83,8 +83,8 @@ class UUIDField extends BaseField {
83
83
  }
84
84
  }
85
85
  if (options.fieldEdge?.enforceSchema &&
86
- !options.fieldEdge.getLoaderOptions) {
87
- throw new Error(`cannot enforceSchema if getLoaderOptions wasn't passed in`);
86
+ !options.fieldEdge.getLoaderInfoFromSchema) {
87
+ throw new Error(`cannot enforceSchema if getLoaderInfoFromSchema wasn't passed in`);
88
88
  }
89
89
  }
90
90
  isBuilder(val) {
@@ -94,19 +94,17 @@ class UUIDField extends BaseField {
94
94
  if (!this.options.fieldEdge?.enforceSchema) {
95
95
  return true;
96
96
  }
97
- // TODO #510 consistency.
98
- const f = (0, camel_case_1.camelCase)(this.options.fieldEdge.schema);
99
- const getLoaderOptions = this.options.fieldEdge.getLoaderOptions;
100
- const loadRowOptions = getLoaderOptions(f);
101
- if (!loadRowOptions) {
102
- throw new Error(`couldn't get loaderOptions for ${f}`);
97
+ const getLoaderInfo = this.options.fieldEdge.getLoaderInfoFromSchema;
98
+ const loaderInfo = getLoaderInfo(this.options.fieldEdge.schema);
99
+ if (!loaderInfo) {
100
+ throw new Error(`couldn't get loaderInfo for ${this.options.fieldEdge.schema}`);
103
101
  }
104
102
  if (this.isBuilder(val)) {
105
- // if builder, the ent type of the builder and the ent type returned by the load constructor should match
106
- return val.ent === loadRowOptions.ent;
103
+ // if builder, the nodeType of the builder and the nodeType of the loaderInfo should match
104
+ return val.nodeType === loaderInfo.nodeType;
107
105
  }
108
106
  // TODO we need context here to make sure that we hit local cache
109
- const row = await loadRowOptions.loaderFactory.createLoader().load(val);
107
+ const row = await loaderInfo.loaderFactory.createLoader().load(val);
110
108
  return row !== null;
111
109
  }
112
110
  }
@@ -570,7 +568,7 @@ class ListField extends BaseField {
570
568
  this.validators.push(validator);
571
569
  return this;
572
570
  }
573
- valid(val) {
571
+ async valid(val) {
574
572
  if (!Array.isArray(val)) {
575
573
  return false;
576
574
  }
@@ -579,15 +577,18 @@ class ListField extends BaseField {
579
577
  return false;
580
578
  }
581
579
  }
582
- if (!this.field.valid) {
580
+ const valid = this.field.valid;
581
+ if (!valid) {
583
582
  return true;
584
583
  }
585
- for (const v of val) {
586
- if (!this.field.valid(v)) {
587
- return false;
588
- }
584
+ const res = valid.apply(this.field, [val[0]]);
585
+ if (util_1.types.isPromise(res)) {
586
+ const ret = await Promise.all(val.map(async (v) => await valid.apply(this.field, [v])));
587
+ return ret.every((v) => v);
589
588
  }
590
- return true;
589
+ const ret = val.map((v) => valid.apply(this.field, [v]));
590
+ const result = ret.every((v) => v);
591
+ return result;
591
592
  }
592
593
  postgresVal(val, jsonType) {
593
594
  if (!jsonType) {
@@ -1,4 +1,4 @@
1
- import { Data, Ent, LoadEntOptions } from "../core/base";
1
+ import { Data, Ent, LoaderInfo } from "../core/base";
2
2
  import { Builder } from "../action/action";
3
3
  export default interface Schema {
4
4
  fields: Field[];
@@ -102,7 +102,7 @@ export interface ForeignKey {
102
102
  disableIndex?: boolean;
103
103
  disableBuilderType?: boolean;
104
104
  }
105
- declare type getLoaderOptionsFn = (type: any) => LoadEntOptions<Ent>;
105
+ declare type getLoaderInfoFn = (type: string) => LoaderInfo;
106
106
  export interface InverseFieldEdge {
107
107
  name: string;
108
108
  edgeConstName?: string;
@@ -113,7 +113,7 @@ export interface FieldEdge {
113
113
  schema: string;
114
114
  inverseEdge?: string | InverseFieldEdge;
115
115
  enforceSchema?: boolean;
116
- getLoaderOptions?: getLoaderOptionsFn;
116
+ getLoaderInfoFromSchema?: getLoaderInfoFn;
117
117
  disableBuilderType?: boolean;
118
118
  }
119
119
  export interface FieldOptions {
@@ -171,6 +171,7 @@ export interface ActionField {
171
171
  nullable?: boolean | NullableListOptions;
172
172
  list?: boolean;
173
173
  actionName?: string;
174
+ excludedFields?: string[];
174
175
  }
175
176
  export interface Action {
176
177
  operation: ActionOperation;
@@ -8,7 +8,7 @@ export declare class User implements Ent {
8
8
  id: ID;
9
9
  accountID: string;
10
10
  nodeType: string;
11
- privacyPolicy: import("../core/base").PrivacyPolicy;
11
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
12
12
  firstName: string;
13
13
  constructor(viewer: Viewer, data: Data);
14
14
  }
@@ -18,7 +18,7 @@ export declare class Event implements Ent {
18
18
  id: ID;
19
19
  accountID: string;
20
20
  nodeType: string;
21
- privacyPolicy: import("../core/base").PrivacyPolicy;
21
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
22
22
  constructor(viewer: Viewer, data: Data);
23
23
  }
24
24
  export declare class Contact implements Ent {
@@ -27,7 +27,7 @@ export declare class Contact implements Ent {
27
27
  id: ID;
28
28
  accountID: string;
29
29
  nodeType: string;
30
- privacyPolicy: import("../core/base").PrivacyPolicy;
30
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
31
31
  constructor(viewer: Viewer, data: Data);
32
32
  }
33
33
  export declare class Group implements Ent {
@@ -36,7 +36,7 @@ export declare class Group implements Ent {
36
36
  id: ID;
37
37
  accountID: string;
38
38
  nodeType: string;
39
- privacyPolicy: import("../core/base").PrivacyPolicy;
39
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
40
40
  constructor(viewer: Viewer, data: Data);
41
41
  }
42
42
  export declare class Message implements Ent {
@@ -45,7 +45,7 @@ export declare class Message implements Ent {
45
45
  id: ID;
46
46
  accountID: string;
47
47
  nodeType: string;
48
- privacyPolicy: import("../core/base").PrivacyPolicy;
48
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
49
49
  constructor(viewer: Viewer, data: Data);
50
50
  }
51
51
  export declare class Address implements Ent {
@@ -54,7 +54,7 @@ export declare class Address implements Ent {
54
54
  id: ID;
55
55
  accountID: string;
56
56
  nodeType: string;
57
- privacyPolicy: import("../core/base").PrivacyPolicy;
57
+ privacyPolicy: import("../core/base").PrivacyPolicy<Ent>;
58
58
  constructor(viewer: Viewer, data: Data);
59
59
  }
60
60
  export interface BuilderSchema<T extends Ent> extends Schema {
@@ -69,9 +69,10 @@ export declare class SimpleBuilder<T extends Ent> implements Builder<T> {
69
69
  existingEnt: T | undefined;
70
70
  ent: EntConstructor<T>;
71
71
  placeholderID: ID;
72
- orchestrator: Orchestrator<T>;
72
+ orchestrator: Orchestrator<T, Data>;
73
73
  fields: Map<string, any>;
74
- constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation?: WriteOperation, existingEnt?: T | undefined, action?: Action<T> | undefined);
74
+ nodeType: string;
75
+ constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation?: WriteOperation, existingEnt?: T | undefined, action?: Action<T, SimpleBuilder<T>, Data> | undefined);
75
76
  build(): Promise<Changeset<T>>;
76
77
  editedEnt(): Promise<T | null>;
77
78
  editedEntX(): Promise<T>;
@@ -83,16 +84,16 @@ export declare class SimpleBuilder<T extends Ent> implements Builder<T> {
83
84
  interface viewerEntLoadFunc {
84
85
  (data: Data): Viewer | Promise<Viewer>;
85
86
  }
86
- export declare class SimpleAction<T extends Ent> implements Action<T> {
87
+ export declare class SimpleAction<T extends Ent> implements Action<T, SimpleBuilder<T>, Data> {
87
88
  viewer: Viewer;
88
89
  private fields;
89
90
  builder: SimpleBuilder<T>;
90
- validators: Validator<T>[];
91
- triggers: Trigger<T>[];
92
- observers: Observer<T>[];
91
+ validators: Validator<SimpleBuilder<T>, Data>[];
92
+ triggers: Trigger<SimpleBuilder<T>, Data>[];
93
+ observers: Observer<SimpleBuilder<T>, Data>[];
93
94
  viewerForEntLoad: viewerEntLoadFunc | undefined;
94
95
  constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation?: WriteOperation, existingEnt?: T | undefined);
95
- getPrivacyPolicy(): import("../core/base").PrivacyPolicy;
96
+ getPrivacyPolicy(): import("../core/base").PrivacyPolicy<Ent>;
96
97
  getInput(): Data;
97
98
  changeset(): Promise<Changeset<T>>;
98
99
  valid(): Promise<boolean>;
@@ -13,6 +13,7 @@ const pluralize_1 = __importDefault(require("pluralize"));
13
13
  const snake_case_1 = require("snake-case");
14
14
  const loaders_1 = require("../core/loaders");
15
15
  const convert_1 = require("../core/convert");
16
+ const camel_case_1 = require("camel-case");
16
17
  class User {
17
18
  constructor(viewer, data) {
18
19
  this.viewer = viewer;
@@ -126,6 +127,7 @@ class SimpleBuilder {
126
127
  }
127
128
  this.ent = schema.ent;
128
129
  const tableName = getTableName(schema);
130
+ this.nodeType = (0, camel_case_1.camelCase)(schema.ent.name);
129
131
  this.orchestrator = new orchestrator_1.Orchestrator({
130
132
  viewer: this.viewer,
131
133
  operation: operation,
@@ -27,6 +27,7 @@ export declare function expectQueryFromRoot(config: queryRootConfig, ...options:
27
27
  export interface mutationRootConfig extends queryConfig {
28
28
  mutation: string;
29
29
  disableInputWrapping?: boolean;
30
+ nullQueryPaths?: string[];
30
31
  }
31
32
  export declare function expectMutation(config: mutationRootConfig, ...options: Option[]): Promise<supertest.SuperTest<supertest.Test>>;
32
33
  export {};
@@ -53,7 +53,7 @@ export declare class UserToFriendRequestsQuery extends AssocEdgeQueryBase<FakeUs
53
53
  }
54
54
  export declare class UserToIncomingFriendRequestsQuery extends AssocEdgeQueryBase<FakeUser, FakeUser, AssocEdge> {
55
55
  constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeUser>);
56
- getPrivacyPolicy(): import("../../core/base").PrivacyPolicy;
56
+ getPrivacyPolicy(): import("../../core/base").PrivacyPolicy<Ent>;
57
57
  sourceEnt(id: ID): Promise<FakeUser | null>;
58
58
  static query(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeUser>): UserToIncomingFriendRequestsQuery;
59
59
  queryContacts(): UserToContactsQuery;
@@ -90,7 +90,7 @@ export declare class UserToEventsInNextWeekQuery extends CustomEdgeQueryBase<Fak
90
90
  constructor(viewer: Viewer, src: ID | FakeUser);
91
91
  static query(viewer: Viewer, src: FakeUser | ID): UserToEventsInNextWeekQuery;
92
92
  sourceEnt(id: ID): Promise<FakeUser | null>;
93
- getPrivacyPolicy(): import("../../core/base").PrivacyPolicy;
93
+ getPrivacyPolicy(): import("../../core/base").PrivacyPolicy<Ent>;
94
94
  }
95
95
  export declare class UserToFollowingQuery extends AssocEdgeQueryBase<FakeUser, Ent, AssocEdge> {
96
96
  constructor(viewer: Viewer, src: EdgeQuerySource<FakeUser, FakeUser>);
@@ -121,6 +121,22 @@ function getDataToReturn(data, colNames, returningAll) {
121
121
  return ret;
122
122
  }
123
123
  exports.getDataToReturn = getDataToReturn;
124
+ function processBeforeStoring(val) {
125
+ if (typeof val !== "string") {
126
+ return val;
127
+ }
128
+ // convert postgres lists into lists before storing
129
+ if (val[0] === "{" && val[val.length - 1] === "}") {
130
+ try {
131
+ // valid json, don't convert
132
+ JSON.parse(val);
133
+ }
134
+ catch (e) {
135
+ return val.substring(1, val.length - 1).split(",");
136
+ }
137
+ }
138
+ return val;
139
+ }
124
140
  function parseInsertStatement(ast, values, // values passed to query
125
141
  returningAll) {
126
142
  const tableName = getTableName(ast.table);
@@ -138,7 +154,7 @@ returningAll) {
138
154
  // INSERT INTO tableName (cols) VALUES (pos args)
139
155
  for (let i = 0; i < columns.length; i++) {
140
156
  let col = columns[i];
141
- data[col] = values[i];
157
+ data[col] = processBeforeStoring(values[i]);
142
158
  }
143
159
  let returningData = null;
144
160
  if (returningAll) {
@@ -411,7 +427,7 @@ function parseUpdateStatement(ast, values, map, returningAll) {
411
427
  for (const set of ast.set) {
412
428
  let col = set.column;
413
429
  let value = getValueFromRegex(set.value, values);
414
- overwrite[col] = value;
430
+ overwrite[col] = processBeforeStoring(value);
415
431
  }
416
432
  let columns = new Set();
417
433
  if (ast.returning) {