@snowtop/ent 0.1.0-alpha35 → 0.1.0-alpha42

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.
@@ -49,7 +49,7 @@ export interface Action<TEnt extends Ent<TViewer>, TBuilder extends Builder<TEnt
49
49
  changeset(): Promise<Changeset>;
50
50
  builder: TBuilder;
51
51
  getPrivacyPolicy(): PrivacyPolicy<TEnt>;
52
- getTriggers?(): Trigger<TEnt, TBuilder, TViewer, TInput, TExistingEnt>[];
52
+ getTriggers?(): (Trigger<TEnt, TBuilder, TViewer, TInput, TExistingEnt> | Trigger<TEnt, TBuilder, TViewer, TInput, TExistingEnt>[])[];
53
53
  getObservers?(): Observer<TEnt, TBuilder, TViewer, TInput, TExistingEnt>[];
54
54
  getValidators?(): Validator<TEnt, TBuilder, TViewer, TInput, TExistingEnt>[];
55
55
  getInput(): TInput;
@@ -333,22 +333,46 @@ class Orchestrator {
333
333
  ]);
334
334
  }
335
335
  async triggers(action, builder, triggers) {
336
- await Promise.all(triggers.map(async (trigger) => {
337
- let ret = await trigger.changeset(builder, action.getInput());
338
- if (Array.isArray(ret)) {
339
- ret = await Promise.all(ret);
340
- }
341
- if (Array.isArray(ret)) {
342
- for (const v of ret) {
343
- if (typeof v === "object") {
344
- this.changesets.push(v);
345
- }
336
+ let groups = [];
337
+ let lastArray = 0;
338
+ let prevWasArray = false;
339
+ for (let i = 0; i < triggers.length; i++) {
340
+ let t = triggers[i];
341
+ if (Array.isArray(t)) {
342
+ if (!prevWasArray) {
343
+ // @ts-ignore
344
+ groups.push(triggers.slice(lastArray, i));
346
345
  }
346
+ groups.push(t);
347
+ prevWasArray = true;
348
+ lastArray++;
347
349
  }
348
- else if (ret) {
349
- this.changesets.push(ret);
350
+ else {
351
+ if (i === triggers.length - 1) {
352
+ // @ts-ignore
353
+ groups.push(triggers.slice(lastArray, i + 1));
354
+ }
355
+ prevWasArray = false;
350
356
  }
351
- }));
357
+ }
358
+ for (const triggers of groups) {
359
+ await Promise.all(triggers.map(async (trigger) => {
360
+ let ret = await trigger.changeset(builder, action.getInput());
361
+ if (Array.isArray(ret)) {
362
+ ret = await Promise.all(ret);
363
+ }
364
+ if (Array.isArray(ret)) {
365
+ for (const v of ret) {
366
+ if (typeof v === "object") {
367
+ this.changesets.push(v);
368
+ }
369
+ }
370
+ }
371
+ else if (ret) {
372
+ this.changesets.push(ret);
373
+ }
374
+ }));
375
+ }
352
376
  }
353
377
  async validators(validators, action, builder) {
354
378
  let promises = [];
package/core/context.js CHANGED
@@ -39,7 +39,7 @@ class ContextCache {
39
39
  const key = this.getkey(options);
40
40
  let rows = m.get(key);
41
41
  if (rows) {
42
- (0, logger_1.log)("query", {
42
+ (0, logger_1.log)("cache", {
43
43
  "cache-hit": key,
44
44
  "tableName": options.tableName,
45
45
  });
@@ -54,7 +54,7 @@ class ContextCache {
54
54
  const key = this.getkey(options);
55
55
  let row = m.get(key);
56
56
  if (row) {
57
- (0, logger_1.log)("query", {
57
+ (0, logger_1.log)("cache", {
58
58
  "cache-hit": key,
59
59
  "tableName": options.tableName,
60
60
  });
package/core/ent.js CHANGED
@@ -38,7 +38,7 @@ class cacheMap {
38
38
  get(key) {
39
39
  const ret = this.m.get(key);
40
40
  if (ret) {
41
- (0, logger_1.log)("query", {
41
+ (0, logger_1.log)("cache", {
42
42
  "dataloader-cache-hit": key,
43
43
  "tableName": this.options.tableName,
44
44
  });
@@ -37,12 +37,12 @@ class cacheMap {
37
37
  // might be a lot?
38
38
  // TODO this is not the best log format
39
39
  // was designed for ObjectLoader time. Now we have different needs e.g. count, assoc etc
40
- (0, logger_1.log)("query", {
40
+ (0, logger_1.log)("cache", {
41
41
  "dataloader-cache-hit": key,
42
42
  "tableName": this.options.tableName,
43
43
  });
44
44
  // } else {
45
- // log("query", {
45
+ // log("cache", {
46
46
  // "dataloader-cache-miss": key,
47
47
  // "tableName": options.tableName,
48
48
  // });
@@ -50,21 +50,21 @@ class cacheMap {
50
50
  return ret;
51
51
  }
52
52
  set(key, value) {
53
- // log("query", {
53
+ // log("cache", {
54
54
  // "dataloader-cache-set": key,
55
55
  // "tableName": options.tableName,
56
56
  // });
57
57
  return this.m.set(key, value);
58
58
  }
59
59
  delete(key) {
60
- // log("query", {
60
+ // log("cache", {
61
61
  // "dataloader-cache-delete": key,
62
62
  // "tableName": options.tableName,
63
63
  // });
64
64
  return this.m.delete(key);
65
65
  }
66
66
  clear() {
67
- // log("query", {
67
+ // log("cache", {
68
68
  // "dataloader-cache-clear": true,
69
69
  // "tableName": options.tableName,
70
70
  // });
package/core/logger.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare type logType = "query" | "warn" | "info" | "error" | "debug";
1
+ declare type logType = "query" | "warn" | "info" | "error" | "debug" | "cache";
2
2
  export declare function setLogLevels(levels: logType | logType[]): void;
3
3
  export declare function clearLogLevels(): void;
4
4
  export declare function log(level: logType, msg: any): void;
package/core/logger.js CHANGED
@@ -7,6 +7,7 @@ var m = {
7
7
  info: "log",
8
8
  error: "error",
9
9
  debug: "debug",
10
+ cache: "log",
10
11
  };
11
12
  var logLevels = new Map();
12
13
  function setLogLevels(levels) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.1.0-alpha35",
3
+ "version": "0.1.0-alpha42",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -83,6 +83,12 @@ class StructField extends field_1.BaseField {
83
83
  }
84
84
  promises.push(field.valid(val));
85
85
  }
86
+ for (const k in obj) {
87
+ // extra undefined fields are invalid
88
+ if (this.options.fields[k] === undefined) {
89
+ return false;
90
+ }
91
+ }
86
92
  if (!valid) {
87
93
  return valid;
88
94
  }
@@ -80,9 +80,12 @@ export declare class SimpleBuilder<T extends Ent, TExistingEnt extends TMaybleNu
80
80
  orchestrator: Orchestrator<T, Data, Viewer>;
81
81
  fields: Map<string, any>;
82
82
  nodeType: string;
83
+ m: Map<string, any>;
83
84
  constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation: WriteOperation, existingEnt: TExistingEnt, action?: Action<T, SimpleBuilder<T>, Viewer, Data> | undefined);
84
85
  getInput(): Data;
85
86
  updateInput(input: Data): void;
87
+ storeData(k: string, v: any): void;
88
+ getStoredData(k: string): any;
86
89
  build(): Promise<Changeset>;
87
90
  editedEnt(): Promise<T | null>;
88
91
  editedEntX(): Promise<T>;
@@ -100,7 +103,7 @@ export declare class SimpleAction<T extends Ent, TExistingEnt extends TMaybleNul
100
103
  builder: SimpleBuilder<T, TExistingEnt>;
101
104
  viewerForEntLoad: viewerEntLoadFunc | undefined;
102
105
  constructor(viewer: Viewer, schema: BuilderSchema<T>, fields: Map<string, any>, operation: WriteOperation | undefined, existingEnt: TExistingEnt);
103
- getTriggers(): Trigger<T, SimpleBuilder<T>>[];
106
+ getTriggers(): (Trigger<T, SimpleBuilder<T>> | Array<Trigger<T, SimpleBuilder<T>>>)[];
104
107
  getValidators(): Validator<T, SimpleBuilder<T>>[];
105
108
  getObservers(): Observer<T, SimpleBuilder<T>>[];
106
109
  getPrivacyPolicy(): PrivacyPolicy<Ent<Viewer<Ent<any> | null, ID | null>>, Viewer<Ent<any> | null, ID | null>>;
@@ -150,6 +150,7 @@ class SimpleBuilder {
150
150
  this.schema = schema;
151
151
  this.operation = operation;
152
152
  this.existingEnt = existingEnt;
153
+ this.m = new Map();
153
154
  // create dynamic placeholder
154
155
  // TODO: do we need to use this as the node when there's an existingEnt
155
156
  // same for generated builders.
@@ -230,6 +231,14 @@ class SimpleBuilder {
230
231
  }
231
232
  }
232
233
  }
234
+ // store data in Builder that can be retrieved by another validator, trigger, observer later in the action
235
+ storeData(k, v) {
236
+ this.m.set(k, v);
237
+ }
238
+ // retrieve data stored in this Builder with key
239
+ getStoredData(k) {
240
+ return this.m.get(k);
241
+ }
233
242
  build() {
234
243
  return this.orchestrator.build();
235
244
  }
@@ -11,10 +11,12 @@ export declare class TransformAction implements TransformFile {
11
11
  rawString?: undefined;
12
12
  traversed?: undefined;
13
13
  imports?: undefined;
14
+ removeImports?: undefined;
14
15
  } | {
15
16
  rawString: string;
16
17
  traversed: boolean;
17
18
  imports: Map<string, string[]>;
19
+ removeImports: string[];
18
20
  node?: undefined;
19
21
  } | undefined;
20
22
  }
@@ -25,11 +25,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.TransformAction = void 0;
26
26
  const typescript_1 = __importDefault(require("typescript"));
27
27
  const ast_1 = require("../tsc/ast");
28
- const action_1 = require("../action");
29
28
  const viewer_1 = require("../core/viewer");
30
29
  const path = __importStar(require("path"));
31
30
  const snake_case_1 = require("snake-case");
32
- function findInput(file, classInfo, sourceFile) {
31
+ // returns input and importPath
32
+ function getBaseFileInfo(file, classInfo, sourceFile) {
33
33
  // @ts-ignore
34
34
  const importStatements = sourceFile.statements.filter((stmt) => typescript_1.default.isImportDeclaration(stmt));
35
35
  for (const imp of importStatements) {
@@ -49,13 +49,19 @@ function findInput(file, classInfo, sourceFile) {
49
49
  .filter((imp) => imp.trim() && imp.endsWith("Input"))
50
50
  .map((v) => v.trim());
51
51
  if (inputs.length === 1) {
52
- return inputs[0];
52
+ return {
53
+ input: inputs[0],
54
+ importPath: impInfo.importPath,
55
+ };
53
56
  }
54
57
  if (inputs.length && classInfo.name.endsWith("Action")) {
55
58
  const prefix = classInfo.name.slice(0, classInfo.name.length - 6);
56
59
  inputs = inputs.filter((imp) => imp.slice(0, imp.length - 5) === prefix);
57
60
  if (inputs.length === 1) {
58
- return inputs[0];
61
+ return {
62
+ input: inputs[0],
63
+ importPath: impInfo.importPath,
64
+ };
59
65
  }
60
66
  }
61
67
  }
@@ -66,17 +72,20 @@ let m = {
66
72
  triggers: {
67
73
  m: "getTriggers",
68
74
  i: "Trigger",
75
+ suffix: "Triggers",
69
76
  },
70
77
  observers: {
71
78
  m: "getObservers",
72
79
  i: "Observer",
80
+ suffix: "Observers",
73
81
  },
74
82
  validators: {
75
83
  m: "getValidators",
76
84
  i: "Validator",
85
+ suffix: "Validators",
77
86
  },
78
87
  };
79
- function getConversionInfo(mm) {
88
+ function getConversionInfo(mm, actionName) {
80
89
  if (mm.kind !== typescript_1.default.SyntaxKind.PropertyDeclaration) {
81
90
  return null;
82
91
  }
@@ -89,6 +98,8 @@ function getConversionInfo(mm) {
89
98
  text,
90
99
  method: v.m,
91
100
  interface: v.i,
101
+ // CreateFooActionTriggers etc
102
+ methodType: actionName + v.suffix,
92
103
  };
93
104
  }
94
105
  class TransformAction {
@@ -109,21 +120,19 @@ class TransformAction {
109
120
  // require action
110
121
  const p = require(path.join(process.cwd(), "./" + file.slice(0, -3)));
111
122
  const action = new p.default(new viewer_1.LoggedOutViewer(), {});
123
+ const actionName = action.constructor.name;
112
124
  const builder = action.builder.constructor.name;
113
125
  const nodeName = action.builder.ent.name;
114
- const existingEnt = action.builder.operation === action_1.WriteOperation.Insert
115
- ? `${nodeName} | null`
116
- : nodeName;
117
126
  const viewer = this.customInfo.viewerInfo.name;
118
- const input = findInput(file, classInfo, sourceFile);
119
- if (!input) {
127
+ const baseInfo = getBaseFileInfo(file, classInfo, sourceFile);
128
+ if (!baseInfo) {
120
129
  return;
121
130
  }
122
131
  let klassContents = "";
123
132
  let traversed = false;
124
133
  let newImports = [];
125
134
  for (const mm of node.members) {
126
- const conv = getConversionInfo(mm);
135
+ const conv = getConversionInfo(mm, actionName);
127
136
  if (conv !== null) {
128
137
  const property = mm;
129
138
  // if invalid, bounce
@@ -132,10 +141,10 @@ class TransformAction {
132
141
  }
133
142
  traversed = true;
134
143
  const pp = property.initializer.getFullText(sourceFile).trim();
135
- const code = `${conv.method}(): ${conv.interface}<${nodeName}, ${builder}<${input}, ${existingEnt}>, ${viewer}, ${input}, ${existingEnt}>[] {
144
+ const code = `${conv.method}(): ${conv.methodType} {
136
145
  return ${pp}
137
146
  }`;
138
- newImports.push(conv.interface);
147
+ newImports.push(conv.methodType);
139
148
  klassContents += (0, ast_1.getPreText)(contents, mm, sourceFile) + code;
140
149
  }
141
150
  else {
@@ -149,10 +158,9 @@ class TransformAction {
149
158
  [viewer],
150
159
  ],
151
160
  [
152
- (0, ast_1.transformRelative)(file, "src/ent", this.customInfo.relativeImports),
153
- [nodeName],
161
+ (0, ast_1.transformRelative)(file, baseInfo.importPath, this.customInfo.relativeImports),
162
+ newImports,
154
163
  ],
155
- ["@snowtop/ent/action", newImports],
156
164
  [
157
165
  (0, ast_1.transformRelative)(file, builderPath, this.customInfo.relativeImports),
158
166
  [builder],
@@ -163,6 +171,8 @@ class TransformAction {
163
171
  rawString: classInfo.wrapClassContents(klassContents),
164
172
  traversed,
165
173
  imports,
174
+ removeImports: ["Trigger", "Observer", "Validator"],
175
+ // not removing FooBuilder incase it's still somehow used in type of inline builders
166
176
  };
167
177
  }
168
178
  }