copper-sdk 0.7.0 → 0.8.0

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/lib/copper-sdk.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- /*! *****************************************************************************
3
+ /******************************************************************************
4
4
  Copyright (c) Microsoft Corporation.
5
5
 
6
6
  Permission to use, copy, modify, and/or distribute this software for any
@@ -14,17 +14,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
14
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
15
  PERFORMANCE OF THIS SOFTWARE.
16
16
  ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol */
17
18
 
18
- var __assign = function() {
19
- __assign = Object.assign || function __assign(t) {
20
- for (var s, i = 1, n = arguments.length; i < n; i++) {
21
- s = arguments[i];
22
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
23
- }
24
- return t;
25
- };
26
- return __assign.apply(this, arguments);
27
- };
28
19
 
29
20
  function __awaiter(thisArg, _arguments, P, generator) {
30
21
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -36,630 +27,520 @@ function __awaiter(thisArg, _arguments, P, generator) {
36
27
  });
37
28
  }
38
29
 
39
- function __generator(thisArg, body) {
40
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
41
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
42
- function verb(n) { return function (v) { return step([n, v]); }; }
43
- function step(op) {
44
- if (f) throw new TypeError("Generator is already executing.");
45
- while (_) try {
46
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
47
- if (y = 0, t) op = [op[0] & 2, t.value];
48
- switch (op[0]) {
49
- case 0: case 1: t = op; break;
50
- case 4: _.label++; return { value: op[1], done: false };
51
- case 5: _.label++; y = op[1]; op = [0]; continue;
52
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
53
- default:
54
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
55
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
56
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
57
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
58
- if (t[2]) _.ops.pop();
59
- _.trys.pop(); continue;
60
- }
61
- op = body.call(thisArg, _);
62
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
63
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
64
- }
65
- }
30
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
31
+ var e = new Error(message);
32
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
33
+ };
66
34
 
67
- var version = "0.7.0";
35
+ var version = "0.8.0";
68
36
 
69
- var ENTITY_PATH_MAP = {
70
- lead: 'leads',
71
- person: 'people',
72
- company: 'companies',
73
- opportunity: 'opportunities',
74
- task: 'tasks',
75
- project: 'projects',
37
+ const ENTITY_PATH_MAP = {
38
+ lead: 'leads',
39
+ person: 'people',
40
+ company: 'companies',
41
+ opportunity: 'opportunities',
42
+ task: 'tasks',
43
+ project: 'projects',
76
44
  };
77
45
 
78
- var UITarget;
79
- (function (UITarget) {
80
- UITarget["ActivityLog"] = "ActivityLog";
81
- UITarget["ListView"] = "ListView";
82
- UITarget["Related"] = "Related";
46
+ var UITarget;
47
+ (function (UITarget) {
48
+ UITarget["ActivityLog"] = "ActivityLog";
49
+ UITarget["ListView"] = "ListView";
50
+ UITarget["Related"] = "Related";
83
51
  })(UITarget || (UITarget = {}));
84
52
 
85
- function logActivityDataGenerator(context, _a) {
86
- var activityType = _a.activityType, details = _a.details, activityDate = _a.activityDate;
87
- var url = '/v1/activities';
88
- var data = {
89
- parent: {
90
- type: context.type,
91
- id: context.id,
92
- },
93
- type: {
94
- category: 'user',
95
- id: activityType,
96
- },
97
- details: details,
98
- };
99
- if (activityDate) {
100
- data.activity_date = activityDate;
101
- }
102
- return {
103
- url: url,
104
- method: 'POST',
105
- data: data,
106
- target: {
107
- name: UITarget.ActivityLog,
108
- },
109
- };
110
- }
111
- function createEntityDataGenerator(context, _a) {
112
- var entityType = _a.entityType, data = _a.data;
113
- var url = "/v1/" + ENTITY_PATH_MAP[entityType];
114
- var target = entityType === context.type
115
- ? {
116
- name: UITarget.ListView,
117
- data: {
118
- entityType: entityType,
119
- entityData: data,
120
- },
121
- }
122
- : null;
123
- return {
124
- url: url,
125
- method: 'POST',
126
- data: data,
127
- target: target,
128
- };
129
- }
130
- function relateEntityDataGenerator(context, _a) {
131
- var entityType = _a.entityType, entityId = _a.entityId, data = _a.data;
132
- var url = "/v1/" + ENTITY_PATH_MAP[entityType] + "/" + entityId + "/related";
133
- var isCurrentEntity = entityType === context.type && entityId === context.id;
134
- var target = isCurrentEntity
135
- ? {
136
- name: UITarget.Related,
137
- data: data,
138
- }
139
- : null;
140
- return {
141
- url: url,
142
- method: 'POST',
143
- data: {
144
- resource: data,
145
- },
146
- target: target,
147
- };
53
+ function logActivityDataGenerator(context, { activityType, details, activityDate, }) {
54
+ const url = '/v1/activities';
55
+ const data = {
56
+ parent: {
57
+ type: context.type,
58
+ id: context.id,
59
+ },
60
+ type: {
61
+ category: 'user',
62
+ id: activityType,
63
+ },
64
+ details,
65
+ };
66
+ if (activityDate) {
67
+ data.activity_date = activityDate;
68
+ }
69
+ return {
70
+ url,
71
+ method: 'POST',
72
+ data,
73
+ target: {
74
+ name: UITarget.ActivityLog,
75
+ },
76
+ };
77
+ }
78
+ function createEntityDataGenerator(context, { entityType, data, }) {
79
+ const url = `/v1/${ENTITY_PATH_MAP[entityType]}`;
80
+ const target = entityType === context.type
81
+ ? {
82
+ name: UITarget.ListView,
83
+ data: {
84
+ entityType,
85
+ entityData: data,
86
+ },
87
+ }
88
+ : null;
89
+ return {
90
+ url,
91
+ method: 'POST',
92
+ data,
93
+ target,
94
+ };
95
+ }
96
+ function relateEntityDataGenerator(context, { entityType, entityId, data, }) {
97
+ const url = `/v1/${ENTITY_PATH_MAP[entityType]}/${entityId}/related`;
98
+ const isCurrentEntity = entityType === context.type && entityId === context.id;
99
+ const target = isCurrentEntity
100
+ ? {
101
+ name: UITarget.Related,
102
+ data,
103
+ }
104
+ : null;
105
+ return {
106
+ url,
107
+ method: 'POST',
108
+ data: {
109
+ resource: data,
110
+ },
111
+ target,
112
+ };
148
113
  }
149
114
 
150
- var Deferred = /** @class */ (function () {
151
- function Deferred() {
152
- var _this = this;
153
- this.resolve = function (value) {
154
- _this._resolve(value);
155
- };
156
- this.reject = function (reason) {
157
- _this._reject(reason);
158
- };
159
- this._promise = new Promise(function (resolve, reject) {
160
- _this._resolve = resolve;
161
- _this._reject = reject;
162
- });
163
- }
164
- Object.defineProperty(Deferred.prototype, "promise", {
165
- get: function () {
166
- return this._promise;
167
- },
168
- enumerable: false,
169
- configurable: true
170
- });
171
- return Deferred;
172
- }());
115
+ class Deferred {
116
+ static resetNextId() {
117
+ Deferred._nextId = 0;
118
+ }
119
+ static getNextId() {
120
+ return Deferred._nextId++;
121
+ }
122
+ constructor() {
123
+ this.resolve = (value) => {
124
+ this._resolve(value);
125
+ };
126
+ this.reject = (reason) => {
127
+ this._reject(reason);
128
+ };
129
+ this._promise = new Promise((resolve, reject) => {
130
+ this._resolve = resolve;
131
+ this._reject = reject;
132
+ });
133
+ this._id = Deferred.getNextId();
134
+ }
135
+ get promise() {
136
+ return this._promise;
137
+ }
138
+ get id() {
139
+ return this._id;
140
+ }
141
+ }
142
+ Deferred._nextId = 0;
173
143
 
174
- /**
175
- * getParameterByName
176
- */
177
- function getParameterByName(name, url) {
178
- if (url === void 0) { url = ''; }
179
- if (!url) {
180
- url = window.location.href;
181
- }
182
- name = name.replace(/[[]]/g, '\\$&');
183
- var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
184
- var results = regex.exec(url);
185
- if (!results || !results[2]) {
186
- return '';
187
- }
188
- return decodeURIComponent(results[2].replace(/\+/g, ' '));
189
- }
190
- function log() {
191
- var msg = [];
192
- for (var _i = 0; _i < arguments.length; _i++) {
193
- msg[_i] = arguments[_i];
194
- }
195
- console.log.apply(console, msg); // tslint:disable-line
196
- }
197
- function checkEnvironment() {
198
- // when the running environment is node.js, throwing error
199
- if (typeof window === 'undefined') {
200
- log('Copper can only run in browser environment');
201
- return false;
202
- }
203
- if (window.top === window) {
204
- log('Copper should be inside an iframe, otherwise it might not work as expected.');
205
- }
206
- return true;
207
- }
208
- /**
209
- * This method has side effect,
210
- * it will alter the obj passed in
211
- */
212
- function createArrayWhenEmpty(obj, name) {
213
- if (!obj[name]) {
214
- obj[name] = [];
215
- }
216
- }
217
- function delayExecution(func, delay) {
218
- if (delay === void 0) { delay = 1000; }
219
- setTimeout(function () {
220
- func();
221
- }, delay);
144
+ /**
145
+ * getParameterByName
146
+ */
147
+ function getParameterByName(name, url = '') {
148
+ if (!url) {
149
+ url = window.location.href;
150
+ }
151
+ name = name.replace(/[[]]/g, '\\$&');
152
+ const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
153
+ const results = regex.exec(url);
154
+ if (!results || !results[2]) {
155
+ return '';
156
+ }
157
+ return decodeURIComponent(results[2].replace(/\+/g, ' '));
158
+ }
159
+ function log(...msg) {
160
+ console.log(...msg); // tslint:disable-line
161
+ }
162
+ function checkEnvironment() {
163
+ // when the running environment is node.js, throwing error
164
+ if (typeof window === 'undefined') {
165
+ log('Copper can only run in browser environment');
166
+ return false;
167
+ }
168
+ if (window.top === window) {
169
+ log('Copper should be inside an iframe, otherwise it might not work as expected.');
170
+ }
171
+ return true;
172
+ }
173
+ /**
174
+ * This method has side effect,
175
+ * it will alter the obj passed in
176
+ */
177
+ function createArrayWhenEmpty(obj, name) {
178
+ if (!obj[name]) {
179
+ obj[name] = [];
180
+ }
181
+ }
182
+ function delayExecution(func, delay = 1000) {
183
+ setTimeout(() => {
184
+ func();
185
+ }, delay);
222
186
  }
223
187
 
224
- var EntityModel = /** @class */ (function () {
225
- function EntityModel(type, entityData, editableFields, onSave) {
226
- if (editableFields === void 0) { editableFields = []; }
227
- var propertyDefinitions = this._getEntityDataDefinition(entityData, editableFields);
228
- // override the type getter
229
- // we don't want type to be enumerable
230
- // since we want to be aligned with developer api
231
- propertyDefinitions.type = {
232
- enumerable: false,
233
- writable: false,
234
- value: type,
235
- };
236
- // override _onSave function
237
- propertyDefinitions._onSave = {
238
- enumerable: false,
239
- value: onSave,
240
- };
241
- Object.defineProperties(this, propertyDefinitions);
242
- }
243
- EntityModel.prototype.save = function () {
244
- return __awaiter(this, void 0, void 0, function () {
245
- return __generator(this, function (_a) {
246
- switch (_a.label) {
247
- case 0:
248
- if (!this._onSave) return [3 /*break*/, 2];
249
- return [4 /*yield*/, this._onSave(this)];
250
- case 1: return [2 /*return*/, _a.sent()];
251
- case 2: return [2 /*return*/, null];
252
- }
253
- });
254
- });
255
- };
256
- EntityModel.prototype.toJSON = function () {
257
- return JSON.stringify(this.toObject());
258
- };
259
- EntityModel.prototype.toObject = function () {
260
- var _this = this;
261
- var obj = {};
262
- Object.keys(this).forEach(function (key) {
263
- obj[key] = _this[key];
264
- });
265
- return obj;
266
- };
267
- EntityModel.prototype._getEntityDataDefinition = function (entityData, editableFields) {
268
- if (editableFields === void 0) { editableFields = []; }
269
- var propertyDefinitions = {};
270
- Object.keys(entityData).forEach(function (key) {
271
- if (editableFields.indexOf(key) === -1) {
272
- propertyDefinitions[key] = {
273
- get: function () {
274
- return entityData[key];
275
- },
276
- set: function () {
277
- log("property " + key + " is read only");
278
- },
279
- enumerable: true,
280
- };
281
- }
282
- else {
283
- propertyDefinitions[key] = {
284
- value: entityData[key],
285
- writable: true,
286
- enumerable: true,
287
- };
288
- }
289
- });
290
- return propertyDefinitions;
291
- };
292
- return EntityModel;
293
- }());
188
+ class EntityModel {
189
+ constructor(type, entityData, editableFields = [], onSave) {
190
+ const propertyDefinitions = this._getEntityDataDefinition(entityData, editableFields);
191
+ // override the type getter
192
+ // we don't want type to be enumerable
193
+ // since we want to be aligned with developer api
194
+ propertyDefinitions.type = {
195
+ enumerable: false,
196
+ writable: false,
197
+ value: type,
198
+ };
199
+ // override _onSave function
200
+ propertyDefinitions._onSave = {
201
+ enumerable: false,
202
+ value: onSave,
203
+ };
204
+ Object.defineProperties(this, propertyDefinitions);
205
+ }
206
+ save() {
207
+ return __awaiter(this, void 0, void 0, function* () {
208
+ if (this._onSave) {
209
+ return yield this._onSave(this);
210
+ }
211
+ return null;
212
+ });
213
+ }
214
+ toJSON() {
215
+ return JSON.stringify(this.toObject());
216
+ }
217
+ toObject() {
218
+ const obj = {};
219
+ Object.keys(this).forEach((key) => {
220
+ obj[key] = this[key];
221
+ });
222
+ return obj;
223
+ }
224
+ _getEntityDataDefinition(entityData, editableFields = []) {
225
+ const propertyDefinitions = {};
226
+ Object.keys(entityData).forEach((key) => {
227
+ if (editableFields.indexOf(key) === -1) {
228
+ propertyDefinitions[key] = {
229
+ get() {
230
+ return entityData[key];
231
+ },
232
+ set() {
233
+ log(`property ${key} is read only`);
234
+ },
235
+ enumerable: true,
236
+ };
237
+ }
238
+ else {
239
+ propertyDefinitions[key] = {
240
+ value: entityData[key],
241
+ writable: true,
242
+ enumerable: true,
243
+ };
244
+ }
245
+ });
246
+ return propertyDefinitions;
247
+ }
248
+ }
294
249
 
295
- var Copper = /** @class */ (function () {
296
- /**
297
- * Creates an instance of Copper.
298
- * @param {*} [_win=window] has to be any type to support testing
299
- * @memberof Copper
300
- */
301
- function Copper(parentOrigin, instanceId, options, _win) {
302
- if (_win === void 0) { _win = window; }
303
- this.parentOrigin = parentOrigin;
304
- this.instanceId = instanceId;
305
- this.options = options;
306
- this._win = _win;
307
- /**
308
- * store deferred queues by name
309
- */
310
- this.deferredQueues = {};
311
- /**
312
- * store event callbacks by event name
313
- */
314
- this.events = {};
315
- if (!this.parentOrigin || !this.instanceId) {
316
- throw new TypeError('parentOrigin or instanceId is empty');
317
- }
318
- this._listenMessage();
319
- // listen to contextUpdated event
320
- this._subscribeContextUpdated();
321
- // notify parent frame init
322
- this._postMessage('init');
323
- }
324
- Copper.init = function () {
325
- var parentOrigin = getParameterByName('origin');
326
- var instanceId = getParameterByName('instanceId');
327
- var options = {
328
- isGlobal: getParameterByName('isGlobal') === '1',
329
- };
330
- if (!checkEnvironment()) {
331
- throw new Error('Environment checking does not pass.');
332
- }
333
- return new Copper(parentOrigin, instanceId, options);
334
- };
335
- Object.defineProperty(Copper, "version", {
336
- get: function () {
337
- return version;
338
- },
339
- enumerable: false,
340
- configurable: true
341
- });
342
- Object.defineProperty(Copper.prototype, "win", {
343
- get: function () {
344
- return this._win;
345
- },
346
- enumerable: false,
347
- configurable: true
348
- });
349
- Copper.prototype.getContext = function () {
350
- return __awaiter(this, void 0, void 0, function () {
351
- var messageData;
352
- return __generator(this, function (_a) {
353
- switch (_a.label) {
354
- case 0: return [4 /*yield*/, this._deferredPost('getContext')];
355
- case 1:
356
- messageData = _a.sent();
357
- return [2 /*return*/, this._createContextModel(messageData)];
358
- }
359
- });
360
- });
361
- };
362
- Copper.prototype.getUserInfo = function () {
363
- return __awaiter(this, void 0, void 0, function () {
364
- return __generator(this, function (_a) {
365
- return [2 /*return*/, this._deferredPost('getUserInfo')];
366
- });
367
- });
368
- };
369
- Copper.prototype.getRouteInfo = function () {
370
- return __awaiter(this, void 0, void 0, function () {
371
- return __generator(this, function (_a) {
372
- return [2 /*return*/, this._deferredPost('getRouteInfo')];
373
- });
374
- });
375
- };
376
- Copper.prototype.saveContext = function (context) {
377
- return __awaiter(this, void 0, void 0, function () {
378
- var messageData;
379
- return __generator(this, function (_a) {
380
- switch (_a.label) {
381
- case 0: return [4 /*yield*/, this._deferredPost('saveContext', {
382
- data: {
383
- entityType: context.type,
384
- entityData: context.toObject(),
385
- },
386
- })];
387
- case 1:
388
- messageData = _a.sent();
389
- return [2 /*return*/, this._createContextModel(messageData)];
390
- }
391
- });
392
- });
393
- };
394
- Copper.prototype.setAppUI = function (data) {
395
- this._postMessage('setUI', { data: data });
396
- };
397
- Copper.prototype.showModal = function (params) {
398
- if (params === void 0) { params = {}; }
399
- this._postMessage('showModal', { params: params });
400
- };
401
- Copper.prototype.closeModal = function () {
402
- this._postMessage('closeModal');
403
- };
404
- /**
405
- * Allows developer to send message to another instance of its app
406
- * e.g. Sending data from modal to sidebar, so sidebar can display some data immediately
407
- *
408
- * @param target another instance/location of the app. '*' means broadcast to all other locations.
409
- */
410
- Copper.prototype.publishMessage = function (messageType, target, msg) {
411
- if (msg === void 0) { msg = {}; }
412
- this._postMessage('publishMessage', {
413
- target: target,
414
- data: {
415
- type: messageType,
416
- msg: msg,
417
- },
418
- });
419
- };
420
- Copper.prototype.logActivity = function (activityType, details, activityDate, refreshDelay) {
421
- if (refreshDelay === void 0) { refreshDelay = 0; }
422
- return __awaiter(this, void 0, void 0, function () {
423
- var context, data;
424
- return __generator(this, function (_a) {
425
- switch (_a.label) {
426
- case 0: return [4 /*yield*/, this._getCachedContext()];
427
- case 1:
428
- context = _a.sent();
429
- data = logActivityDataGenerator(context, {
430
- activityType: activityType,
431
- details: details,
432
- activityDate: activityDate,
433
- });
434
- return [2 /*return*/, this._action(data, refreshDelay)];
435
- }
436
- });
437
- });
438
- };
439
- Copper.prototype.createEntity = function (entityType, entityData, refreshDelay) {
440
- if (refreshDelay === void 0) { refreshDelay = 0; }
441
- return __awaiter(this, void 0, void 0, function () {
442
- var context, e_1, apiOptions, url, method, data, target, result;
443
- var _this = this;
444
- return __generator(this, function (_a) {
445
- switch (_a.label) {
446
- case 0:
447
- _a.trys.push([0, 2, , 3]);
448
- return [4 /*yield*/, this._getCachedContext()];
449
- case 1:
450
- context = _a.sent();
451
- return [3 /*break*/, 3];
452
- case 2:
453
- e_1 = _a.sent();
454
- // we allow create entity be called without actual context
455
- context = {};
456
- return [3 /*break*/, 3];
457
- case 3:
458
- apiOptions = createEntityDataGenerator(context, {
459
- entityType: entityType,
460
- data: entityData,
461
- });
462
- url = apiOptions.url, method = apiOptions.method, data = apiOptions.data, target = apiOptions.target;
463
- return [4 /*yield*/, this.api(url, { method: method, body: JSON.stringify(data) })];
464
- case 4:
465
- result = _a.sent();
466
- if (target && target.data) {
467
- target.data.entityData = result;
468
- delayExecution(function () {
469
- _this.refreshUI(target);
470
- }, refreshDelay);
471
- }
472
- return [2 /*return*/, result];
473
- }
474
- });
475
- });
476
- };
477
- Copper.prototype.relateEntity = function (entityType, entityId, relateData, refreshDelay) {
478
- if (refreshDelay === void 0) { refreshDelay = 0; }
479
- return __awaiter(this, void 0, void 0, function () {
480
- var context, data;
481
- return __generator(this, function (_a) {
482
- switch (_a.label) {
483
- case 0: return [4 /*yield*/, this._getCachedContext()];
484
- case 1:
485
- context = _a.sent();
486
- data = relateEntityDataGenerator(context, {
487
- entityType: entityType,
488
- entityId: parseInt(entityId, 10),
489
- data: relateData,
490
- });
491
- return [2 /*return*/, this._action(data, refreshDelay)];
492
- }
493
- });
494
- });
495
- };
496
- Copper.prototype.refreshUI = function (target) {
497
- this._postMessage('refreshUI', { target: target });
498
- };
499
- Copper.prototype.on = function (eventName, cb) {
500
- createArrayWhenEmpty(this.events, eventName);
501
- this.events[eventName].push(cb);
502
- };
503
- Copper.prototype.trigger = function (eventName, data) {
504
- var _this = this;
505
- if (this.events[eventName]) {
506
- this.events[eventName].forEach(function (cb) {
507
- cb.call(_this, data);
508
- });
509
- }
510
- };
511
- Copper.prototype.api = function (url, options) {
512
- if (!url) {
513
- return Promise.reject({
514
- id: 'sdk-api',
515
- version: Copper.version,
516
- detail: 'url cannot be empty',
517
- });
518
- }
519
- if (options && options.body) {
520
- try {
521
- JSON.parse(options.body);
522
- }
523
- catch (e) {
524
- return Promise.reject({
525
- id: 'sdk-api',
526
- version: Copper.version,
527
- detail: 'body must be a valid JSON string',
528
- });
529
- }
530
- }
531
- return this._deferredPost('api', {
532
- url: url,
533
- options: options,
534
- });
535
- };
536
- Copper.prototype.navigateToEntityDetail = function (entityType, entityId) {
537
- return this._deferredPost('navigateToEntityDetail', { entityType: entityType, entityId: entityId });
538
- };
539
- Copper.prototype.getSelectedRecords = function (_a) {
540
- var _b = _a === void 0 ? {} : _a, _c = _b.pageSize, pageSize = _c === void 0 ? 100 : _c, _d = _b.pageNumber, pageNumber = _d === void 0 ? 0 : _d;
541
- return this._deferredPost('getSelectedRecords', { pageSize: pageSize, pageNumber: pageNumber });
542
- };
543
- Copper.prototype.getConfig = function () {
544
- return this._deferredPost('getConfig');
545
- };
546
- Copper.prototype._getCachedContext = function () {
547
- return __awaiter(this, void 0, void 0, function () {
548
- var context;
549
- return __generator(this, function (_a) {
550
- switch (_a.label) {
551
- case 0:
552
- if (this._context) {
553
- return [2 /*return*/, this._context];
554
- }
555
- return [4 /*yield*/, this.getContext()];
556
- case 1:
557
- context = (_a.sent()).context;
558
- return [2 /*return*/, context];
559
- }
560
- });
561
- });
562
- };
563
- Copper.prototype._postMessage = function (type, message) {
564
- if (message === void 0) { message = {}; }
565
- this.win.top.postMessage(__assign(__assign({}, message), {
566
- // as a credential to the parent frame, so parent frame can recoganize the origin
567
- instanceId: this.instanceId,
568
- // tell parent frame current sdk version
569
- version: version,
570
- // type of message
571
- type: type }), this.parentOrigin);
572
- };
573
- Copper.prototype._listenMessage = function () {
574
- var _this = this;
575
- this.win.addEventListener('message', function (event) {
576
- if (!_this._isOriginValid(event)) {
577
- return;
578
- }
579
- // if type is a deferred type, we resolve it
580
- // otherwise we do something else
581
- _this._resolveDeferred(event.data.type, event.data);
582
- // if event type exists, we pass the event to SDK
583
- // so sdk user can subscribe those events
584
- if (event.data.type) {
585
- _this.trigger(event.data.type, event.data.msg || event.data.data);
586
- }
587
- }, false);
588
- };
589
- Copper.prototype._isOriginValid = function (event) {
590
- // only check origin for now
591
- return event.origin === this.parentOrigin;
592
- };
593
- Copper.prototype._enqueueDeferred = function (queueName, deferred) {
594
- createArrayWhenEmpty(this.deferredQueues, queueName);
595
- this.deferredQueues[queueName].push(deferred);
596
- };
597
- Copper.prototype._resolveDeferred = function (queueName, data) {
598
- if (!this.deferredQueues[queueName]) {
599
- return;
600
- }
601
- var deferred = this.deferredQueues[queueName].shift();
602
- if (deferred) {
603
- if (data.error) {
604
- return deferred.reject(data.error);
605
- }
606
- deferred.resolve(data.data);
607
- }
608
- };
609
- Copper.prototype._createContextModel = function (_a) {
610
- var entityType = _a.entityType, entityData = _a.entityData, editableFields = _a.editableFields;
611
- var context = new EntityModel(entityType, entityData, editableFields, this.saveContext.bind(this));
612
- this._context = context;
613
- return {
614
- type: entityType,
615
- context: context,
616
- };
617
- };
618
- Copper.prototype._action = function (_a, delay) {
619
- var url = _a.url, method = _a.method, data = _a.data, target = _a.target;
620
- return __awaiter(this, void 0, void 0, function () {
621
- var result;
622
- var _this = this;
623
- return __generator(this, function (_b) {
624
- switch (_b.label) {
625
- case 0: return [4 /*yield*/, this.api(url, { method: method, body: JSON.stringify(data) })];
626
- case 1:
627
- result = _b.sent();
628
- if (target) {
629
- delayExecution(function () {
630
- _this.refreshUI(target);
631
- }, delay);
632
- }
633
- return [2 /*return*/, result];
634
- }
635
- });
636
- });
637
- };
638
- Copper.prototype._createDeferredMethod = function (queueName, executor) {
639
- var deferred = new Deferred();
640
- this._enqueueDeferred(queueName, deferred);
641
- executor();
642
- return deferred.promise;
643
- };
644
- Copper.prototype._deferredPost = function (name, data) {
645
- var _this = this;
646
- return this._createDeferredMethod(name, function () {
647
- if (data) {
648
- _this._postMessage(name, data);
649
- }
650
- else {
651
- _this._postMessage(name);
652
- }
653
- });
654
- };
655
- Copper.prototype._subscribeContextUpdated = function () {
656
- var _this = this;
657
- this.on('contextUpdated', function () {
658
- // remove _context caching
659
- _this._context = null;
660
- });
661
- };
662
- return Copper;
663
- }());
250
+ class Copper {
251
+ static init() {
252
+ const parentOrigin = getParameterByName('origin');
253
+ const instanceId = getParameterByName('instanceId');
254
+ const options = {
255
+ isGlobal: getParameterByName('isGlobal') === '1',
256
+ };
257
+ if (!checkEnvironment()) {
258
+ throw new Error('Environment checking does not pass.');
259
+ }
260
+ return new Copper(parentOrigin, instanceId, options);
261
+ }
262
+ static get version() {
263
+ return version;
264
+ }
265
+ /**
266
+ * Creates an instance of Copper.
267
+ * @param {*} [_win=window] has to be any type to support testing
268
+ * @memberof Copper
269
+ */
270
+ constructor(parentOrigin, instanceId, options, _win = window) {
271
+ this.parentOrigin = parentOrigin;
272
+ this.instanceId = instanceId;
273
+ this.options = options;
274
+ this._win = _win;
275
+ /**
276
+ * store deferred queues by name
277
+ */
278
+ this.deferredQueues = {};
279
+ /**
280
+ * store event callbacks by event name
281
+ */
282
+ this.events = {};
283
+ if (!this.parentOrigin || !this.instanceId) {
284
+ throw new TypeError('parentOrigin or instanceId is empty');
285
+ }
286
+ this._listenMessage();
287
+ // listen to contextUpdated event
288
+ this._subscribeContextUpdated();
289
+ // notify parent frame init
290
+ this._postMessage('init');
291
+ }
292
+ get win() {
293
+ return this._win;
294
+ }
295
+ getContext() {
296
+ return __awaiter(this, void 0, void 0, function* () {
297
+ const messageData = yield this._deferredPost('getContext');
298
+ return this._createContextModel(messageData);
299
+ });
300
+ }
301
+ getUserInfo() {
302
+ return __awaiter(this, void 0, void 0, function* () {
303
+ return this._deferredPost('getUserInfo');
304
+ });
305
+ }
306
+ getRouteInfo() {
307
+ return __awaiter(this, void 0, void 0, function* () {
308
+ return this._deferredPost('getRouteInfo');
309
+ });
310
+ }
311
+ saveContext(context) {
312
+ return __awaiter(this, void 0, void 0, function* () {
313
+ const messageData = yield this._deferredPost('saveContext', {
314
+ data: {
315
+ entityType: context.type,
316
+ entityData: context.toObject(),
317
+ },
318
+ });
319
+ return this._createContextModel(messageData);
320
+ });
321
+ }
322
+ setAppUI(data) {
323
+ this._postMessage('setUI', { data });
324
+ }
325
+ showModal(params = {}) {
326
+ this._postMessage('showModal', { params });
327
+ }
328
+ closeModal() {
329
+ this._postMessage('closeModal');
330
+ }
331
+ /**
332
+ * Allows developer to send message to another instance of its app
333
+ * e.g. Sending data from modal to sidebar, so sidebar can display some data immediately
334
+ *
335
+ * @param target another instance/location of the app. '*' means broadcast to all other locations.
336
+ */
337
+ publishMessage(messageType, target, msg = {}) {
338
+ this._postMessage('publishMessage', {
339
+ target,
340
+ data: {
341
+ type: messageType,
342
+ msg,
343
+ },
344
+ });
345
+ }
346
+ logActivity(activityType_1, details_1, activityDate_1) {
347
+ return __awaiter(this, arguments, void 0, function* (activityType, details, activityDate, refreshDelay = 0) {
348
+ const context = yield this._getCachedContext();
349
+ const data = logActivityDataGenerator(context, {
350
+ activityType,
351
+ details,
352
+ activityDate,
353
+ });
354
+ return this._action(data, refreshDelay);
355
+ });
356
+ }
357
+ createEntity(entityType_1, entityData_1) {
358
+ return __awaiter(this, arguments, void 0, function* (entityType, entityData, refreshDelay = 0) {
359
+ let context;
360
+ try {
361
+ context = yield this._getCachedContext();
362
+ }
363
+ catch (e) {
364
+ // we allow create entity be called without actual context
365
+ context = {};
366
+ }
367
+ const apiOptions = createEntityDataGenerator(context, {
368
+ entityType,
369
+ data: entityData,
370
+ });
371
+ const { url, method, data, target } = apiOptions;
372
+ const result = yield this.api(url, { method, body: JSON.stringify(data) });
373
+ if (target && target.data) {
374
+ target.data.entityData = result;
375
+ delayExecution(() => {
376
+ this.refreshUI(target);
377
+ }, refreshDelay);
378
+ }
379
+ return result;
380
+ });
381
+ }
382
+ relateEntity(entityType_1, entityId_1, relateData_1) {
383
+ return __awaiter(this, arguments, void 0, function* (entityType, entityId, relateData, refreshDelay = 0) {
384
+ const context = yield this._getCachedContext();
385
+ const data = relateEntityDataGenerator(context, {
386
+ entityType,
387
+ entityId: parseInt(entityId, 10),
388
+ data: relateData,
389
+ });
390
+ return this._action(data, refreshDelay);
391
+ });
392
+ }
393
+ refreshUI(target) {
394
+ this._postMessage('refreshUI', { target });
395
+ }
396
+ on(eventName, cb) {
397
+ createArrayWhenEmpty(this.events, eventName);
398
+ this.events[eventName].push(cb);
399
+ }
400
+ trigger(eventName, data) {
401
+ if (this.events[eventName]) {
402
+ this.events[eventName].forEach((cb) => {
403
+ cb.call(this, data);
404
+ });
405
+ }
406
+ }
407
+ api(url, options) {
408
+ if (!url) {
409
+ return Promise.reject({
410
+ id: 'sdk-api',
411
+ version: Copper.version,
412
+ detail: 'url cannot be empty',
413
+ });
414
+ }
415
+ if (options && options.body) {
416
+ try {
417
+ JSON.parse(options.body);
418
+ }
419
+ catch (e) {
420
+ return Promise.reject({
421
+ id: 'sdk-api',
422
+ version: Copper.version,
423
+ detail: 'body must be a valid JSON string',
424
+ });
425
+ }
426
+ }
427
+ return this._deferredPost('api', {
428
+ url,
429
+ options,
430
+ });
431
+ }
432
+ navigateToEntityDetail(entityType, entityId) {
433
+ return this._deferredPost('navigateToEntityDetail', { entityType, entityId });
434
+ }
435
+ getSelectedRecords({ pageSize = 100, pageNumber = 0 } = {}) {
436
+ return this._deferredPost('getSelectedRecords', { pageSize, pageNumber });
437
+ }
438
+ getConfig() {
439
+ return this._deferredPost('getConfig');
440
+ }
441
+ _getCachedContext() {
442
+ return __awaiter(this, void 0, void 0, function* () {
443
+ if (this._context) {
444
+ return this._context;
445
+ }
446
+ const { context } = yield this.getContext();
447
+ return context;
448
+ });
449
+ }
450
+ _postMessage(type, message = {}, id = -1) {
451
+ var _a;
452
+ (_a = this.win.top) === null || _a === void 0 ? void 0 : _a.postMessage(Object.assign(Object.assign({}, message), {
453
+ // as a credential to the parent frame, so parent frame can recoganize the origin
454
+ instanceId: this.instanceId,
455
+ // tell parent frame current sdk version
456
+ version,
457
+ // type of message
458
+ type,
459
+ // optional id for message
460
+ id }), this.parentOrigin);
461
+ }
462
+ _listenMessage() {
463
+ this.win.addEventListener('message', (event) => {
464
+ if (!this._isOriginValid(event)) {
465
+ return;
466
+ }
467
+ // if type is a deferred type, we resolve it
468
+ // otherwise we do something else
469
+ this._resolveDeferred(event.data.type, event.data.id, event.data);
470
+ // if event type exists, we pass the event to SDK
471
+ // so sdk user can subscribe those events
472
+ if (event.data.type) {
473
+ this.trigger(event.data.type, event.data.msg || event.data.data);
474
+ }
475
+ }, false);
476
+ }
477
+ _isOriginValid(event) {
478
+ // only check origin for now
479
+ return event.origin === this.parentOrigin;
480
+ }
481
+ _enqueueDeferred(queueName, deferred) {
482
+ createArrayWhenEmpty(this.deferredQueues, queueName);
483
+ this.deferredQueues[queueName].push(deferred);
484
+ }
485
+ _resolveDeferred(queueName, messageId, data) {
486
+ const queue = this.deferredQueues[queueName];
487
+ if (!queue) {
488
+ return;
489
+ }
490
+ const foundIdx = queue.findIndex((d) => {
491
+ return d.id === messageId;
492
+ });
493
+ const deferred = queue[foundIdx];
494
+ if (deferred) {
495
+ queue.splice(foundIdx, 1);
496
+ if (data.error) {
497
+ return deferred.reject(data.error);
498
+ }
499
+ deferred.resolve(data.data);
500
+ }
501
+ }
502
+ _createContextModel({ entityType, entityData, editableFields, }) {
503
+ const context = new EntityModel(entityType, entityData, editableFields, this.saveContext.bind(this));
504
+ this._context = context;
505
+ return {
506
+ type: entityType,
507
+ context,
508
+ };
509
+ }
510
+ _action(_a, delay_1) {
511
+ return __awaiter(this, arguments, void 0, function* ({ url, method, data, target }, delay) {
512
+ const result = yield this.api(url, { method, body: JSON.stringify(data) });
513
+ if (target) {
514
+ delayExecution(() => {
515
+ this.refreshUI(target);
516
+ }, delay);
517
+ }
518
+ return result;
519
+ });
520
+ }
521
+ _createDeferredMethod(queueName, executor) {
522
+ const deferred = new Deferred();
523
+ this._enqueueDeferred(queueName, deferred);
524
+ executor(deferred);
525
+ return deferred.promise;
526
+ }
527
+ _deferredPost(name, data) {
528
+ return this._createDeferredMethod(name, (deferred) => {
529
+ if (data) {
530
+ this._postMessage(name, data, deferred.id);
531
+ }
532
+ else {
533
+ this._postMessage(name, {}, deferred.id);
534
+ }
535
+ });
536
+ }
537
+ _subscribeContextUpdated() {
538
+ this.on('contextUpdated', () => {
539
+ // remove _context caching
540
+ this._context = null;
541
+ });
542
+ }
543
+ }
664
544
 
665
545
  module.exports = Copper;
546
+ //# sourceMappingURL=copper-sdk.js.map