@coherentglobal/spark-execute-sdk 0.3.11 → 0.3.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherentglobal/spark-execute-sdk",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "description": "",
5
5
  "main": "src/node.js",
6
6
  "browser": "dist/browser.js",
package/src/browser.js CHANGED
@@ -47,7 +47,7 @@ class Spark {
47
47
  /**
48
48
  * @private
49
49
  */
50
- this.fallbackEnabled = false;
50
+ this.priority = ["model", "onlineEndpoint"];
51
51
  }
52
52
  /**
53
53
  *
@@ -85,9 +85,138 @@ class Spark {
85
85
  return model;
86
86
  }
87
87
 
88
+ _findModel(requestMeta) {
89
+ let model = {};
90
+ if (requestMeta.version_id) {
91
+ model = this.model.filter(({ versionId }) => {
92
+ return versionId === requestMeta.version_id;
93
+ });
94
+ } else if (requestMeta.servicename && requestMeta.version) {
95
+ model = this.model.filter(
96
+ ({ metaData }) =>
97
+ metaData.EngineInformation.ServiceName === requestMeta.servicename &&
98
+ metaData.EngineInformation.Revision === requestMeta.version
99
+ );
100
+ } else if (requestMeta.servicename && requestMeta.transaction_date) {
101
+ model = this.model.filter(
102
+ ({ metaData }) =>
103
+ metaData.EngineInformation.ServiceName === requestMeta.servicename &&
104
+ new Date(requestMeta.transaction_date) >=
105
+ new Date(metaData.effectiveStartDate) &&
106
+ new Date(requestMeta.transaction_date) <=
107
+ new Date(metaData.effectiveEndDate)
108
+ );
109
+
110
+ if (model.length > 1) {
111
+ return model
112
+ .sort((versionA, versionB) =>
113
+ versionA.metaData.EngineInformation.Revision.replace(
114
+ /\d+/g,
115
+ (n) => +n + 100000
116
+ ).localCompare(
117
+ versionB.metaData.EngineInformation.Revision.replace(
118
+ /\d+/g,
119
+ (n) => +n + 100000
120
+ )
121
+ )
122
+ )
123
+ .reverse();
124
+ }
125
+ } else if (requestMeta.service_id && requestMeta.version) {
126
+ model = this.model.filter(
127
+ ({ metaData }) =>
128
+ metaData.EngineInformation.ServiceGuid === requestMeta.service_id &&
129
+ metaData.EngineInformation.Revision === requestMeta.version
130
+ );
131
+ } else if (requestMeta.service_id && requestMeta.transaction_date) {
132
+ model = this.model.filter(
133
+ ({ metaData }) =>
134
+ metaData.EngineInformation.ServiceGuid === requestMeta.service_id &&
135
+ new Date(requestMeta.transaction_date) >=
136
+ new Date(metaData.effectiveStartDate) &&
137
+ new Date(requestMeta.transaction_date) <=
138
+ new Date(metaData.effectiveEndDate)
139
+ );
140
+
141
+ if (model.length > 1) {
142
+ return model
143
+ .sort((versionA, versionB) =>
144
+ versionA.metaData.EngineInformation.Revision.replace(
145
+ /\d+/g,
146
+ (n) => +n + 100000
147
+ ).localCompare(
148
+ versionB.metaData.EngineInformation.Revision.replace(
149
+ /\d+/g,
150
+ (n) => +n + 100000
151
+ )
152
+ )
153
+ )
154
+ .reverse();
155
+ }
156
+ } else if (requestMeta.service_uri && requestMeta.transaction_date) {
157
+ const regex = /folders\/(.+)\/services\/(.+)/gi;
158
+ const parts = regex.exec(requestMeta.service_uri);
159
+ let folder, service;
160
+ if (parts) {
161
+ folder = decodeURI(parts[1]);
162
+ service = decodeURI(parts[2]);
163
+ }
164
+
165
+ model = this.model.filter(
166
+ ({ metaData }) =>
167
+ metaData.EngineInformation.ProductName === folder &&
168
+ metaData.EngineInformation.ServiceName === service &&
169
+ new Date(requestMeta.transaction_date) >=
170
+ new Date(metaData.effectiveStartDate) &&
171
+ new Date(requestMeta.transaction_date) <=
172
+ new Date(metaData.effectiveEndDate)
173
+ );
174
+
175
+ if (model.length > 1) {
176
+ return model
177
+ .sort((versionA, versionB) =>
178
+ versionA.metaData.EngineInformation.Revision.replace(
179
+ /\d+/g,
180
+ (n) => +n + 100000
181
+ ).localCompare(
182
+ versionB.metaData.EngineInformation.Revision.replace(
183
+ /\d+/g,
184
+ (n) => +n + 100000
185
+ )
186
+ )
187
+ )
188
+ .reverse();
189
+ }
190
+ } else if (requestMeta.service_uri && requestMeta.version) {
191
+ const regex = /folders\/(.+)\/services\/(.+)/gi;
192
+ const parts = regex.exec(requestMeta.service_uri);
193
+ let folder, service;
194
+ if (parts) {
195
+ folder = decodeURI(parts[1]);
196
+ service = decodeURI(parts[2]);
197
+ }
198
+ model = this.model.filter(
199
+ ({ metaData }) =>
200
+ metaData.EngineInformation.ProductName === folder &&
201
+ metaData.EngineInformation.ServiceName === service &&
202
+ metaData.EngineInformation.Revision === requestMeta.version
203
+ );
204
+ } else {
205
+ throw new Error(
206
+ "Model not found. requestMeta: " +
207
+ JSON.stringify(requestMeta) +
208
+ " tenant: " +
209
+ this.tenant
210
+ );
211
+ }
212
+
213
+ return model[0];
214
+ }
215
+
88
216
  _getModelByMeta(folderName, serviceName) {
89
217
  const model = this.model.find(
90
- m => m?.metaData?.EngineInformation?.ProductName === folderName &&
218
+ (m) =>
219
+ m?.metaData?.EngineInformation?.ProductName === folderName &&
91
220
  m?.metaData?.EngineInformation?.ServiceName === serviceName
92
221
  );
93
222
  if (!model) throw new WasmRunnerErrors.MissingModelError(serviceName);
@@ -99,7 +228,7 @@ class Spark {
99
228
  * Execute model
100
229
  *
101
230
  * @param {object} input
102
- * @param {string} version_id
231
+ * @param {string} [version_id] version_id
103
232
  * @returns {object}
104
233
  */
105
234
  async execute(input, version_id) {
@@ -108,108 +237,114 @@ class Spark {
108
237
  input.request_meta.version_id ||
109
238
  input.request_meta.version_uuid;
110
239
 
111
- const model = this._getModel(versionID);
112
-
113
- if (input) {
114
- let modelUrl = "";
115
-
116
- if (
117
- !this.isCompatible &&
118
- !utils.isEmpty(this.url) &&
119
- this.fallbackEnabled
120
- ) {
121
- let token = "";
122
- if (this.token.constructor.name === "AsyncFunction") {
123
- token = await this.token();
124
- } else {
125
- token = this.token;
126
- }
127
-
128
- if (utils.isEmpty(this.token)) {
129
- throw new WasmRunnerErrors.UnauthorizedError();
130
- }
131
- const header = utils.getAuthHeaders(token, this.authType, this.tenant);
132
-
133
- const options = {
134
- method: "POST",
135
- body: JSON.stringify({
136
- request_data: {},
137
- request_meta: input.request_meta,
138
- }),
139
- headers: { ...{ "content-type": "application/json" }, ...header },
140
- };
240
+ let lookup = {
241
+ model: this.offlineModel,
242
+ onlineEndpoint: this.onlineModelEndpoint,
243
+ };
244
+
245
+ let response;
246
+
247
+ response = await lookup[this.priority[0]](input, versionID, this);
248
+ if (response instanceof Error) {
249
+ response = await lookup[this.priority[1]](input, versionID, this);
250
+ }
251
+
252
+ return response;
253
+ }
141
254
 
142
- modelUrl = new URL(
143
- `/${this.tenant}/api/v3/version/${input.request_meta.version_id}`,
144
- this.url
145
- );
146
- try {
147
- const response = await fetch(modelUrl, options);
148
-
149
- return await response.json();
150
- } catch (err) {
151
- throw new WasmRunnerErrors.UnauthorizedError();
152
- }
153
- } else if (this.isCompatible) {
154
- if (!(registry instanceof WasmRunner)) {
155
-
156
- /**
157
- * Options is the request data the the runner dispatch
158
- * receives from the wasm model
159
- * @param {*} options
160
- * @returns
161
- */
162
- const callback = async (options) => {
163
- const hasFolderName = options?.folder_name
164
- const hasServiceName = options?.service_name
165
- let hasVersionId = options?.version_id
166
- if (hasVersionId && !registry.isExist(hasVersionId)) {
167
- await registry.append({
168
- id: hasVersionId,
169
- url: model.binary,
170
- meta: {
171
- folder_name: model?.metaData?.EngineInformation?.ProductName ?? "",
172
- service_name: model?.metaData?.EngineInformation?.ServiceName ?? ""
173
- }
174
- });
175
- } else {
176
- const model = this._getModelByMeta(hasFolderName, hasServiceName)
177
- hasVersionId = model?.versionId
178
- await registry.append({
179
- id: hasVersionId,
180
- url: model.binary,
181
- meta: {
182
- folder_name: model?.metaData?.EngineInformation?.ProductName ?? "",
183
- service_name: model?.metaData?.EngineInformation?.ServiceName ?? ""
184
- }
185
- });
186
- }
187
- return hasVersionId
255
+ async offlineModel(input, versionID, ds) {
256
+ console.log("OFFLINES");
257
+ try {
258
+ if (!(registry instanceof WasmRunner)) {
259
+ /**
260
+ * Options is the request data the the runner dispatch
261
+ * receives from the wasm model
262
+ * @param {*} options
263
+ * @returns
264
+ */
265
+ const callback = async (options) => {
266
+ const hasFolderName = options?.folder_name;
267
+ const hasServiceName = options?.service_name;
268
+ let hasVersionId = options?.version_id;
269
+ if (hasVersionId && !registry.isExist(hasVersionId)) {
270
+ await registry.append({
271
+ id: hasVersionId,
272
+ url: model.binary,
273
+ meta: {
274
+ folder_name:
275
+ model?.metaData?.EngineInformation?.ProductName ?? "",
276
+ service_name:
277
+ model?.metaData?.EngineInformation?.ServiceName ?? "",
278
+ },
279
+ });
280
+ } else {
281
+ const model = ds._getModelByMeta(hasFolderName, hasServiceName);
282
+ hasVersionId = model?.versionId;
283
+ await registry.append({
284
+ id: hasVersionId,
285
+ url: model.binary,
286
+ meta: {
287
+ folder_name:
288
+ model?.metaData?.EngineInformation?.ProductName ?? "",
289
+ service_name:
290
+ model?.metaData?.EngineInformation?.ServiceName ?? "",
291
+ },
292
+ });
188
293
  }
189
- registry = new WasmRunner("", callback);
190
- }
191
-
192
- if (!registry.isExist(versionID)) {
193
- const model = this._getModel(versionID);
194
- await registry.append({
195
- id: versionID,
196
- url: model.binary,
197
- meta: {
198
- folder_name: model?.folder_name ?? "",
199
- service_name: model?.service_name ?? ""
200
- }
201
- });
202
- }
203
- const result = await registry.execute(input, versionID, () => {
294
+ return hasVersionId;
295
+ };
296
+ registry = new WasmRunner("", callback);
297
+ }
204
298
 
299
+ if (!registry.isExist(versionID)) {
300
+ const model = ds._findModel(versionID);
301
+ await registry.append({
302
+ id: versionID,
303
+ url: model.binary,
304
+ meta: {
305
+ folder_name: model?.folder_name ?? "",
306
+ service_name: model?.service_name ?? "",
307
+ },
205
308
  });
206
-
207
- return result;
208
- } else {
209
- throw new WasmRunnerErrors.NotSupportedError(
210
- "WebAssembly is not supported"
211
- );
212
309
  }
310
+ const result = await registry.execute(input, versionID, () => {});
311
+ return result;
312
+ } catch (err) {
313
+ return err;
314
+ }
315
+ }
316
+
317
+ async onlineModelEndpoint(input, versionID, ds) {
318
+ let token = "";
319
+ if (ds.token.constructor.name === "AsyncFunction") {
320
+ token = await ds.token();
321
+ } else {
322
+ token = ds.token;
323
+ }
324
+
325
+ if (utils.isEmpty(ds.token)) {
326
+ throw new WasmRunnerErrors.UnauthorizedError();
327
+ }
328
+ try {
329
+ const header = utils.getAuthHeaders(token, ds.authType, ds.tenant);
330
+
331
+ const options = {
332
+ method: "POST",
333
+ body: JSON.stringify({
334
+ request_data: {},
335
+ request_meta: input.request_meta,
336
+ }),
337
+ headers: { ...{ "content-type": "application/json" }, ...header },
338
+ };
339
+
340
+ const modelUrl = new URL(`/${ds.tenant}/api/v3/execute`, ds.url);
341
+
342
+ const response = await fetch(modelUrl, options);
343
+
344
+ const result = await response.json();
345
+ return result;
346
+ } catch (err) {
347
+ return err;
213
348
  }
214
349
  }
215
350
  }
package/src/node.js CHANGED
@@ -5,6 +5,7 @@ const logger = require("./logger");
5
5
  const validate = require("./validate.js");
6
6
  const processModels = require("./models.js");
7
7
  const got = require("got");
8
+ const { object } = require("joi");
8
9
 
9
10
  let registry = [];
10
11
 
@@ -46,11 +47,10 @@ class Spark {
46
47
  * @private
47
48
  */
48
49
  this.model = this._models(nodeGenModels);
49
-
50
50
  /**
51
51
  * @private
52
52
  */
53
- this.fallbackEnabled = false;
53
+ this.priority = ["model", "onlineEndpoint"];
54
54
  }
55
55
 
56
56
  /**
@@ -94,11 +94,139 @@ class Spark {
94
94
  return model;
95
95
  }
96
96
 
97
+ _findModel(requestMeta) {
98
+ let model = {};
99
+ if (requestMeta.version_id) {
100
+ model = this.model.filter(({ versionId }) => {
101
+ return versionId === requestMeta.version_id;
102
+ });
103
+ } else if (requestMeta.servicename && requestMeta.version) {
104
+ model = this.model.filter(
105
+ ({ metaData }) =>
106
+ metaData.EngineInformation.ServiceName === requestMeta.servicename &&
107
+ metaData.EngineInformation.Revision === requestMeta.version
108
+ );
109
+ } else if (requestMeta.servicename && requestMeta.transaction_date) {
110
+ model = this.model.filter(
111
+ ({ metaData }) =>
112
+ metaData.EngineInformation.ServiceName === requestMeta.servicename &&
113
+ new Date(requestMeta.transaction_date) >=
114
+ new Date(metaData.effectiveStartDate) &&
115
+ new Date(requestMeta.transaction_date) <=
116
+ new Date(metaData.effectiveEndDate)
117
+ );
118
+
119
+ if (model.length > 1) {
120
+ return model
121
+ .sort((versionA, versionB) =>
122
+ versionA.metaData.EngineInformation.Revision.replace(
123
+ /\d+/g,
124
+ (n) => +n + 100000
125
+ ).localCompare(
126
+ versionB.metaData.EngineInformation.Revision.replace(
127
+ /\d+/g,
128
+ (n) => +n + 100000
129
+ )
130
+ )
131
+ )
132
+ .reverse();
133
+ }
134
+ } else if (requestMeta.service_id && requestMeta.version) {
135
+ model = this.model.filter(
136
+ ({ metaData }) =>
137
+ metaData.EngineInformation.ServiceGuid === requestMeta.service_id &&
138
+ metaData.EngineInformation.Revision === requestMeta.version
139
+ );
140
+ } else if (requestMeta.service_id && requestMeta.transaction_date) {
141
+ model = this.model.filter(
142
+ ({ metaData }) =>
143
+ metaData.EngineInformation.ServiceGuid === requestMeta.service_id &&
144
+ new Date(requestMeta.transaction_date) >=
145
+ new Date(metaData.effectiveStartDate) &&
146
+ new Date(requestMeta.transaction_date) <=
147
+ new Date(metaData.effectiveEndDate)
148
+ );
149
+
150
+ if (model.length > 1) {
151
+ return model
152
+ .sort((versionA, versionB) =>
153
+ versionA.metaData.EngineInformation.Revision.replace(
154
+ /\d+/g,
155
+ (n) => +n + 100000
156
+ ).localCompare(
157
+ versionB.metaData.EngineInformation.Revision.replace(
158
+ /\d+/g,
159
+ (n) => +n + 100000
160
+ )
161
+ )
162
+ )
163
+ .reverse();
164
+ }
165
+ } else if (requestMeta.service_uri && requestMeta.transaction_date) {
166
+ const regex = /folders\/(.+)\/services\/(.+)/gi;
167
+ const parts = regex.exec(requestMeta.service_uri);
168
+ let folder, service;
169
+ if (parts) {
170
+ folder = decodeURI(parts[1]);
171
+ service = decodeURI(parts[2]);
172
+ }
173
+
174
+ model = this.model.filter(
175
+ ({ metaData }) =>
176
+ metaData.EngineInformation.ProductName === folder &&
177
+ metaData.EngineInformation.ServiceName === service &&
178
+ new Date(requestMeta.transaction_date) >=
179
+ new Date(metaData.effectiveStartDate) &&
180
+ new Date(requestMeta.transaction_date) <=
181
+ new Date(metaData.effectiveEndDate)
182
+ );
183
+
184
+ if (model.length > 1) {
185
+ return model
186
+ .sort((versionA, versionB) =>
187
+ versionA.metaData.EngineInformation.Revision.replace(
188
+ /\d+/g,
189
+ (n) => +n + 100000
190
+ ).localCompare(
191
+ versionB.metaData.EngineInformation.Revision.replace(
192
+ /\d+/g,
193
+ (n) => +n + 100000
194
+ )
195
+ )
196
+ )
197
+ .reverse();
198
+ }
199
+ } else if (requestMeta.service_uri && requestMeta.version) {
200
+ const regex = /folders\/(.+)\/services\/(.+)/gi;
201
+ const parts = regex.exec(requestMeta.service_uri);
202
+ let folder, service;
203
+ if (parts) {
204
+ folder = decodeURI(parts[1]);
205
+ service = decodeURI(parts[2]);
206
+ }
207
+ model = this.model.filter(
208
+ ({ metaData }) =>
209
+ metaData.EngineInformation.ProductName === folder &&
210
+ metaData.EngineInformation.ServiceName === service &&
211
+ metaData.EngineInformation.Revision === requestMeta.version
212
+ );
213
+ } else {
214
+ throw new Error(
215
+ "Model not found. requestMeta: " +
216
+ JSON.stringify(requestMeta) +
217
+ " tenant: " +
218
+ this.tenant
219
+ );
220
+ }
221
+
222
+ return model[0];
223
+ }
224
+
97
225
  /**
98
226
  * Execute model
99
227
  *
100
228
  * @param {object} input
101
- * @param {string} version_id
229
+ * @param {string} [version_id] version_id
102
230
  * @returns {object}
103
231
  */
104
232
  async execute(input, version_id) {
@@ -107,85 +235,88 @@ class Spark {
107
235
  input.request_meta.version_id ||
108
236
  input.request_meta.version_uuid;
109
237
 
110
- const model = this._getModel(versionID);
238
+ let lookup = {
239
+ model: this.offlineModel,
240
+ onlineEndpoint: this.onlineModelEndpoint,
241
+ };
111
242
 
112
- // await this.load(model.versionId);
243
+ let response;
113
244
 
114
- logger.info({
115
- EventType: "ExecuteModel",
116
- TextMessage: `Execute uuid: ${model.versionId}`,
117
- });
118
-
119
- if (input) {
120
- let modelUrl = "";
121
-
122
- if (
123
- !this.isCompatible &&
124
- !utils.isEmpty(this.url) &&
125
- this.fallbackEnabled
126
- ) {
127
- let token = "";
128
- if (this.token.constructor.name === "AsyncFunction") {
129
- token = await this.token();
130
- } else {
131
- token = this.token;
132
- }
133
- console.log("TOKEN", token);
134
-
135
- if (utils.isEmpty(this.token)) {
136
- throw new WasmRunnerErrors.UnauthorizedError();
137
- }
138
-
139
- const options = {
140
- headers: utils.getAuthHeaders(token, this.authType, this.tenant),
141
- json: {
142
- request_data: {},
143
- request_meta: input.request_meta,
144
- },
145
- };
146
-
147
- console.log("OPTIONS", options);
148
- modelUrl = new URL(
149
- `/${this.tenant}/api/v3/version/${input.request_meta.version_id}`,
150
- this.url
151
- );
152
-
153
- try {
154
- const response = await got.post(modelUrl, options).json();
155
-
156
- return response;
157
- } catch (err) {
158
- throw new WasmRunnerErrors.UnauthorizedError();
159
- }
160
- } else if (this.isCompatible) {
161
- if (!(registry instanceof WasmRunner)) {
162
- registry = new WasmRunner();
163
- }
164
-
165
- if (!registry.isExist(versionID)) {
166
- await registry.append({
167
- id: versionID,
168
- url: model.binary,
169
- // size,
170
- });
171
- }
172
- const result = await registry.execute(input, versionID);
173
-
174
- return result;
175
- } else {
176
- throw new WasmRunnerErrors.NotSupportedError(
177
- "WebAssembly is not supported"
178
- );
179
- }
180
- } else {
181
- throw new WasmRunnerErrors.BadRequestError("Missing request input.");
245
+ response = await lookup[this.priority[0]](input, versionID, this);
246
+ if (response instanceof Error) {
247
+ response = await lookup[this.priority[1]](input, versionID, this);
182
248
  }
249
+
250
+ return response;
183
251
  }
184
252
 
185
253
  /**
186
254
  * Remove Model
187
255
  */
188
256
  // async remove(versionId) {}
257
+
258
+ async offlineModel(input, versionID, ds) {
259
+ try {
260
+ const model = ds._findModel(input.request_meta);
261
+
262
+ logger.info({
263
+ EventType: "ExecuteModel",
264
+ TextMessage: `Execute uuid: ${model && model?.versionId}`,
265
+ });
266
+ if (!(registry instanceof WasmRunner)) {
267
+ registry = new WasmRunner();
268
+ }
269
+
270
+ if (!registry.isExist(versionID)) {
271
+ await registry.append({
272
+ id: versionID,
273
+ url: model?.binary || "",
274
+ // size,
275
+ });
276
+ }
277
+
278
+ let result = await registry.execute(input, versionID);
279
+
280
+ return result;
281
+ } catch (err) {
282
+ return err;
283
+ }
284
+ }
285
+
286
+ async onlineModelEndpoint(input, versionID, ds) {
287
+ logger.info({
288
+ EventType: "ExecuteOnlineModel",
289
+ TextMessage: `Execute uuid: ${versionID}`,
290
+ });
291
+
292
+ let token = "";
293
+ if (ds.token.constructor.name === "AsyncFunction") {
294
+ token = await ds.token();
295
+ } else {
296
+ token = ds.token;
297
+ }
298
+
299
+ if (utils.isEmpty(ds.token)) {
300
+ throw new WasmRunnerErrors.UnauthorizedError();
301
+ }
302
+ try {
303
+ const options = {
304
+ headers: utils.getAuthHeaders(token, ds.authType, ds.tenant),
305
+ json: {
306
+ request_data: {},
307
+ request_meta: input.request_meta,
308
+ },
309
+ };
310
+
311
+ let modelUrl = new URL(`/${ds.tenant}/api/v3/execute`, ds.url);
312
+
313
+ const result = await got.post(modelUrl, options).json();
314
+
315
+ return result;
316
+ } catch (err) {
317
+ return err;
318
+ }
319
+ }
189
320
  }
190
321
 
191
322
  module.exports = Spark;