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