@twintag/twintag-sdk 0.2.235-TTPL-1970-twintagsdk-397570c85978488f2e5cebf3cab22c0a2faa6217
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/README.md +0 -0
- package/lib/twintag.esm.js +2365 -0
- package/lib/twintag.esm.js.map +1 -0
- package/lib/twintag.js +2378 -0
- package/lib/twintag.js.map +1 -0
- package/lib/types/libs/twintag-sdk/src/index.d.ts +8 -0
- package/lib/types/libs/twintag-sdk/src/lib/base.d.ts +40 -0
- package/lib/types/libs/twintag-sdk/src/lib/client.d.ts +17 -0
- package/lib/types/libs/twintag-sdk/src/lib/environment.d.ts +21 -0
- package/lib/types/libs/twintag-sdk/src/lib/epsilon.d.ts +31 -0
- package/lib/types/libs/twintag-sdk/src/lib/error.model.d.ts +10 -0
- package/lib/types/libs/twintag-sdk/src/lib/fileUploader.d.ts +53 -0
- package/lib/types/libs/twintag-sdk/src/lib/files.d.ts +8 -0
- package/lib/types/libs/twintag-sdk/src/lib/listObject.d.ts +165 -0
- package/lib/types/libs/twintag-sdk/src/lib/offlineOptions.d.ts +2 -0
- package/lib/types/libs/twintag-sdk/src/lib/parser.d.ts +3 -0
- package/lib/types/libs/twintag-sdk/src/lib/project.d.ts +224 -0
- package/lib/types/libs/twintag-sdk/src/lib/sdk.d.ts +30 -0
- package/lib/types/libs/twintag-sdk/src/lib/structuredObject.d.ts +123 -0
- package/lib/types/libs/twintag-sdk/src/lib/twintag.d.ts +38 -0
- package/lib/types/libs/twintag-sdk/src/lib/version.d.ts +4 -0
- package/lib/types/libs/twintag-sdk/src/lib/view.d.ts +368 -0
- package/lib/types/libs/twintag-sdk/src/lib/virtual.d.ts +92 -0
- package/package.json +15 -0
|
@@ -0,0 +1,2365 @@
|
|
|
1
|
+
/*! *****************************************************************************
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
|
|
4
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
5
|
+
purpose with or without fee is hereby granted.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
***************************************************************************** */
|
|
15
|
+
|
|
16
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
17
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// DO NOT EDIT: This file is automatically generated by build/version.js
|
|
27
|
+
/**
|
|
28
|
+
* The twintag-sdk version.
|
|
29
|
+
*/
|
|
30
|
+
const VERSION = '0.2.235-TTPL-1970-twintagsdk-397570c85978488f2e5cebf3cab22c0a2faa6217';
|
|
31
|
+
|
|
32
|
+
class TwintagErrorValue {
|
|
33
|
+
}
|
|
34
|
+
class TwintagError extends Error {
|
|
35
|
+
constructor(message, errors, name, stack) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = name;
|
|
38
|
+
this.stack = stack;
|
|
39
|
+
this.errors = errors;
|
|
40
|
+
}
|
|
41
|
+
setMessage(message) {
|
|
42
|
+
this.message = message;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const explicitDisableOffline = {
|
|
47
|
+
offlineAction: 'explicit disable offline',
|
|
48
|
+
disabled: true
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
class Client {
|
|
55
|
+
constructor(token) {
|
|
56
|
+
this.token = token;
|
|
57
|
+
}
|
|
58
|
+
do(path, args, offlineOptions, skipParse, skipAuth // TODO: Deprecate in virtual web endpoint.
|
|
59
|
+
) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
// first check if we are in a browser context
|
|
62
|
+
if (typeof window !== 'undefined') {
|
|
63
|
+
if (window.twintagOfflineSupport && !window.twintagOfflineSupport.onLine) {
|
|
64
|
+
if (offlineOptions && offlineOptions.disabled) {
|
|
65
|
+
return this.doOnline(path, args, offlineOptions, skipParse, skipAuth);
|
|
66
|
+
}
|
|
67
|
+
return this.doOffline(path, args, offlineOptions, skipParse, skipAuth);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return this.doOnline(path, args, offlineOptions, skipParse, skipAuth);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
doOnline(path, args, offlineOptions, skipParse, skipAuth // TODO: Deprecate in virtual web endpoint.
|
|
74
|
+
) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
//Inject authorization for our host
|
|
77
|
+
const headers = new Headers(args === null || args === void 0 ? void 0 : args.headers);
|
|
78
|
+
if (this.token && !skipAuth) {
|
|
79
|
+
if (!headers.get('Authorization')) {
|
|
80
|
+
headers.set('Authorization', 'Bearer ' + this.token);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//Add client analytics
|
|
84
|
+
headers.set('X-Client-Name', 'twintag.js');
|
|
85
|
+
headers.set('X-Client-Version', VERSION);
|
|
86
|
+
args.headers = headers;
|
|
87
|
+
const resp = yield fetch(new Request(path, args));
|
|
88
|
+
if (!resp.ok) {
|
|
89
|
+
// custom API error
|
|
90
|
+
const err = yield resp.json();
|
|
91
|
+
return [{}, this.CreateTwintagError(err)];
|
|
92
|
+
}
|
|
93
|
+
if (skipParse) {
|
|
94
|
+
if (!resp.body) {
|
|
95
|
+
return [{}, undefined];
|
|
96
|
+
}
|
|
97
|
+
return [resp.body, undefined];
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const res = yield resp.json();
|
|
101
|
+
return [res, undefined];
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const err = new TwintagErrorValue();
|
|
105
|
+
err.title = 'failed to parse response';
|
|
106
|
+
err.detail = 'something went wrong when parsing response';
|
|
107
|
+
return [{}, this.CreateTwintagError([err])];
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
doOffline(path, args, offlineOptions, skipParse, skipAuth // TODO: Deprecate in virtual web endpoint.
|
|
112
|
+
) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const offlineSupportHandler = window.twintagOfflineSupport;
|
|
115
|
+
if (offlineSupportHandler) {
|
|
116
|
+
offlineSupportHandler.addOfflineRequest({
|
|
117
|
+
path,
|
|
118
|
+
args,
|
|
119
|
+
offlineOptions,
|
|
120
|
+
skipParse,
|
|
121
|
+
skipAuth
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return [{}, undefined];
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
get(path, offlineOptions, args, skipAuth // TODO: Deprecate
|
|
128
|
+
) {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
if (!args) {
|
|
131
|
+
args = {};
|
|
132
|
+
}
|
|
133
|
+
args.method = 'GET';
|
|
134
|
+
return yield this.do(path, args, offlineOptions, false, skipAuth);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
put(path, body, offlineOptions, args, skipAuth // TODO: Deprecate
|
|
138
|
+
) {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
if (!args) {
|
|
141
|
+
args = {};
|
|
142
|
+
}
|
|
143
|
+
args.method = 'PUT';
|
|
144
|
+
if (!args.body && body) {
|
|
145
|
+
args.body = JSON.stringify(body);
|
|
146
|
+
}
|
|
147
|
+
return yield this.do(path, args, offlineOptions, false, skipAuth);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
post(path, body, args, skipAuth) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
if (!args) {
|
|
153
|
+
args = {};
|
|
154
|
+
}
|
|
155
|
+
args.method = 'POST';
|
|
156
|
+
if (!args.body && body) {
|
|
157
|
+
args.body = JSON.stringify(body);
|
|
158
|
+
}
|
|
159
|
+
return yield this.do(path, args, explicitDisableOffline, false, skipAuth);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
delete(path, body, offlineOptions, args) {
|
|
163
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
+
if (!args) {
|
|
165
|
+
args = {};
|
|
166
|
+
}
|
|
167
|
+
args.method = 'delete';
|
|
168
|
+
if (!args.body && body) {
|
|
169
|
+
args.body = JSON.stringify(body);
|
|
170
|
+
}
|
|
171
|
+
return yield this.do(path, args, offlineOptions, true);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
CreateTwintagError(err) {
|
|
175
|
+
if (err && err.errors && err.errors.length > 0) {
|
|
176
|
+
return new TwintagError(err.errors[0].detail, err.errors[0], err.errors[0].title);
|
|
177
|
+
}
|
|
178
|
+
return new TwintagError('Failed to perform the request', err, 'Twintag Error');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
class Environment {
|
|
183
|
+
constructor() {
|
|
184
|
+
this._host = 'https://twintag.io';
|
|
185
|
+
this._adminHost = '';
|
|
186
|
+
this._cachingHost = '';
|
|
187
|
+
this.useCaching = false;
|
|
188
|
+
this.autoDetect = true;
|
|
189
|
+
}
|
|
190
|
+
get host() {
|
|
191
|
+
this.autoDetectOrigin();
|
|
192
|
+
return this._host;
|
|
193
|
+
}
|
|
194
|
+
set host(host) {
|
|
195
|
+
this.autoDetect = false;
|
|
196
|
+
this._host = host;
|
|
197
|
+
}
|
|
198
|
+
get adminHost() {
|
|
199
|
+
this.autoDetectOrigin();
|
|
200
|
+
return this._adminHost;
|
|
201
|
+
}
|
|
202
|
+
set adminHost(adminHost) {
|
|
203
|
+
this.autoDetect = false;
|
|
204
|
+
this._adminHost = adminHost;
|
|
205
|
+
}
|
|
206
|
+
get cachingHost() {
|
|
207
|
+
this.autoDetectOrigin();
|
|
208
|
+
return this._cachingHost;
|
|
209
|
+
}
|
|
210
|
+
set cachingHost(cachingHost) {
|
|
211
|
+
this.autoDetect = false;
|
|
212
|
+
this._cachingHost = cachingHost;
|
|
213
|
+
}
|
|
214
|
+
autoDetectOrigin() {
|
|
215
|
+
var _a, _b;
|
|
216
|
+
if (!this.autoDetect)
|
|
217
|
+
return;
|
|
218
|
+
if (typeof window !== 'undefined'
|
|
219
|
+
&& (window === null || window === void 0 ? void 0 : window.origin) !== undefined
|
|
220
|
+
&& ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.hostname) !== "localhost"
|
|
221
|
+
&& ((_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.hostname) !== "127.0.0.1") {
|
|
222
|
+
this._host = window.origin;
|
|
223
|
+
}
|
|
224
|
+
const base = new URL(this._host);
|
|
225
|
+
const adminSub = 'admin.';
|
|
226
|
+
const cachingSub = 'cache.';
|
|
227
|
+
this._adminHost = `${base.protocol}//${adminSub}${base.host}`;
|
|
228
|
+
this._cachingHost = `${base.protocol}//${cachingSub}${base.host}`;
|
|
229
|
+
this.autoDetect = false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Default environment config.
|
|
234
|
+
*
|
|
235
|
+
* @Internal
|
|
236
|
+
*/
|
|
237
|
+
const environment = new Environment();
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Twintag SDK.
|
|
241
|
+
*
|
|
242
|
+
* @packageDocumentation
|
|
243
|
+
*/
|
|
244
|
+
/**
|
|
245
|
+
* SetHost allows you to overwrite the Twintag domain.
|
|
246
|
+
*
|
|
247
|
+
* @hidden
|
|
248
|
+
*/
|
|
249
|
+
function setHost(host) {
|
|
250
|
+
environment.host = host;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* SetAdminHost allows you to overwrite the Twintag administrative domain.
|
|
254
|
+
*
|
|
255
|
+
* @hidden
|
|
256
|
+
*/
|
|
257
|
+
function setAdminHost(host) {
|
|
258
|
+
environment.adminHost = host;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* setCachingHost allows you to overwrite the Twintag caching domain.
|
|
262
|
+
*
|
|
263
|
+
* @hidden
|
|
264
|
+
*/
|
|
265
|
+
function setCachingHost(host) {
|
|
266
|
+
environment.cachingHost = host;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* retryRequest allows you to retry a cached/stored request
|
|
270
|
+
*
|
|
271
|
+
* @hidden
|
|
272
|
+
*/
|
|
273
|
+
function retryRequest(request) {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
request.skipParse = true; //no need to parse the response as this is a retry, so our app is in a different state
|
|
276
|
+
const client = new Client();
|
|
277
|
+
return yield client.doOnline(request.path, request.args, request.offlineOptions, request.skipParse, request.skipAuth);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
class Parser {
|
|
282
|
+
static parseSpecialTypes(data) {
|
|
283
|
+
let singleInstance = false;
|
|
284
|
+
if (!(data instanceof Array)) {
|
|
285
|
+
singleInstance = true;
|
|
286
|
+
data = [data];
|
|
287
|
+
}
|
|
288
|
+
data.forEach((instance) => {
|
|
289
|
+
for (const prop in instance) {
|
|
290
|
+
if (prop.startsWith('$')) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (instance[`$${prop}Type`]) {
|
|
294
|
+
switch (instance[`$${prop}Type`]) {
|
|
295
|
+
case 'dateTime':
|
|
296
|
+
instance[prop] = new Date(instance[prop]);
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
return singleInstance ? data[0] : data;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
class FileUploader {
|
|
307
|
+
/**
|
|
308
|
+
* Construct listObject with objectApiName, scemaScope, viewId and client.
|
|
309
|
+
*
|
|
310
|
+
* @param objectAPIName
|
|
311
|
+
* @param client
|
|
312
|
+
* @param viewId
|
|
313
|
+
* @param schemaScope
|
|
314
|
+
*
|
|
315
|
+
* @internal
|
|
316
|
+
*/
|
|
317
|
+
constructor(client, viewId, signedUrl, fileQid, instanceQid) {
|
|
318
|
+
this._client = client;
|
|
319
|
+
this.viewId = viewId;
|
|
320
|
+
this.instanceQid = instanceQid;
|
|
321
|
+
this.fileQid = fileQid;
|
|
322
|
+
this.signedUrl = signedUrl;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Upload uploads the file provided file to the resppective structured data column
|
|
326
|
+
*
|
|
327
|
+
* @param file, file to be uploaded
|
|
328
|
+
*
|
|
329
|
+
*/
|
|
330
|
+
Upload(file) {
|
|
331
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
332
|
+
this.uploadFile(file);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Private method to upload file.
|
|
337
|
+
*
|
|
338
|
+
* @param file type properties
|
|
339
|
+
*
|
|
340
|
+
* @internal
|
|
341
|
+
*/
|
|
342
|
+
uploadFile(file) {
|
|
343
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
344
|
+
yield this.uploadToS3(this.signedUrl, file);
|
|
345
|
+
yield this.endUpload(this.instanceQid, this.fileQid);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Private method to upload file to s3.
|
|
350
|
+
*
|
|
351
|
+
* @param uploadUrl presigned s3 upload url
|
|
352
|
+
* @param file file object to upload
|
|
353
|
+
*
|
|
354
|
+
* @internal
|
|
355
|
+
*/
|
|
356
|
+
uploadToS3(uploadUrl, file) {
|
|
357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
358
|
+
const body = yield file.arrayBuffer();
|
|
359
|
+
return this._client.do(uploadUrl, { method: 'put', body: body }, explicitDisableOffline, true, true);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Private method to end upload call.
|
|
364
|
+
*
|
|
365
|
+
* @param fileContext instance qid
|
|
366
|
+
* @param fileQid file qid
|
|
367
|
+
*
|
|
368
|
+
* @internal
|
|
369
|
+
*/
|
|
370
|
+
endUpload(fileContext, fileQid) {
|
|
371
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
372
|
+
let url = this.fileUrl();
|
|
373
|
+
url += '/end';
|
|
374
|
+
const body = {
|
|
375
|
+
fileQid: fileQid,
|
|
376
|
+
fileContext: fileContext,
|
|
377
|
+
};
|
|
378
|
+
this._client.put(url, body);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
fileUrl() {
|
|
382
|
+
if (this.viewId !== '') {
|
|
383
|
+
return environment.host + '/api/v1/views/' + this.viewId + '/data/files';
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
return environment.adminHost + '/api/v1/data/files';
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* A list object class represents data from a list type of object.
|
|
393
|
+
* This object can be used to interact with the list of data of a list object.
|
|
394
|
+
* CRUD operations can be performed on this object
|
|
395
|
+
*/
|
|
396
|
+
class ListObject {
|
|
397
|
+
/**
|
|
398
|
+
* Construct listObject with objectApiName, scemaScope, viewId and client.
|
|
399
|
+
*
|
|
400
|
+
* @param objectAPIName
|
|
401
|
+
* @param client
|
|
402
|
+
* @param viewId
|
|
403
|
+
* @param schemaScope
|
|
404
|
+
*
|
|
405
|
+
* @internal
|
|
406
|
+
*/
|
|
407
|
+
constructor(objectAPIName, client, viewId, projectId, useCaching = false) {
|
|
408
|
+
this._useCaching = false;
|
|
409
|
+
this._client = client;
|
|
410
|
+
this.viewId = viewId;
|
|
411
|
+
this.objectApiName = objectAPIName;
|
|
412
|
+
this._projectId = projectId;
|
|
413
|
+
this._useCaching = useCaching;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get a record from list object with the specified id.
|
|
417
|
+
* Optional parameter lang can be passed to get data in a specific language.
|
|
418
|
+
*
|
|
419
|
+
* Example:
|
|
420
|
+
* Without language
|
|
421
|
+
* ```js
|
|
422
|
+
* await object.get('')
|
|
423
|
+
* ```
|
|
424
|
+
*
|
|
425
|
+
* With language parameter
|
|
426
|
+
* ```js
|
|
427
|
+
* await object.get('', 'en')
|
|
428
|
+
* ```
|
|
429
|
+
*
|
|
430
|
+
* @param id Id value of the record
|
|
431
|
+
* @param lang: optional language value. Allowed inputs are "all" or any language defined in project languages. If no value is passed, then project's default language will be used for returning data
|
|
432
|
+
*
|
|
433
|
+
* @category ListObject
|
|
434
|
+
*/
|
|
435
|
+
get(id, lang, offlineOptions) {
|
|
436
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
437
|
+
let url = '';
|
|
438
|
+
if (this._useCaching) {
|
|
439
|
+
if (this.viewId === '') {
|
|
440
|
+
url = `${environment.cachingHost}/data/${this.objectApiName}/${id}?withSDFileURL=false&schemaScope=${this._projectId}`;
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
url = `${environment.cachingHost}/api/v1/views/${this.viewId}/data/${this.objectApiName}/${id}?withSDFileURL=false&`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
url = this.dataUrl(id);
|
|
448
|
+
}
|
|
449
|
+
url += lang
|
|
450
|
+
? `${url.indexOf('?') < 0 ? '?' : '&'}language=${lang === 'all' ? '*' : lang}`
|
|
451
|
+
: '';
|
|
452
|
+
const [res, err] = yield this._client.get(url, offlineOptions);
|
|
453
|
+
if (err) {
|
|
454
|
+
err.setMessage(`failed to get data: ${err.message}`);
|
|
455
|
+
throw err;
|
|
456
|
+
}
|
|
457
|
+
return Parser.parseSpecialTypes(res);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Add data to list object for the specified view.
|
|
462
|
+
*
|
|
463
|
+
* @param data An object representing the data
|
|
464
|
+
*
|
|
465
|
+
* @category ListObject
|
|
466
|
+
*/
|
|
467
|
+
insert(data, offlineOptions) {
|
|
468
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
469
|
+
const url = this.dataUrl();
|
|
470
|
+
const fileTypes = this.parseForSpecialTypes(data);
|
|
471
|
+
const [res, err] = yield this._client.put(url, data, offlineOptions, {
|
|
472
|
+
headers: { 'Content-Type': 'application/json' },
|
|
473
|
+
});
|
|
474
|
+
if (err) {
|
|
475
|
+
err.setMessage(`failed to insert data: ${err.message}`);
|
|
476
|
+
throw err;
|
|
477
|
+
}
|
|
478
|
+
return yield this.parseResponse(res, fileTypes);
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Private method to parse file types in request.
|
|
483
|
+
* Ideally validate if the value is of File type. Since at the time of development File polyfill was not injected * to epsilon, checking for instance of File is not possible. adding null check for value deletion support
|
|
484
|
+
* @param data
|
|
485
|
+
*
|
|
486
|
+
* @internal
|
|
487
|
+
*/
|
|
488
|
+
parseForSpecialTypes(data) {
|
|
489
|
+
const fileType = [];
|
|
490
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
491
|
+
if (value instanceof Date) {
|
|
492
|
+
const tzoffset = new Date().getTimezoneOffset() * 60000; // offset in milliseconds
|
|
493
|
+
const dateTimeInMilliSeconds = new Date(value).getTime();
|
|
494
|
+
data[key] = new Date(dateTimeInMilliSeconds - tzoffset).toISOString().split('T').join(' ').split('.')[0];
|
|
495
|
+
}
|
|
496
|
+
else if (value && typeof value === 'object') {
|
|
497
|
+
fileType.push({
|
|
498
|
+
apiName: key,
|
|
499
|
+
file: data[key],
|
|
500
|
+
});
|
|
501
|
+
data[key] = {
|
|
502
|
+
name: value.name,
|
|
503
|
+
size: value.size,
|
|
504
|
+
fileContent: value.fileContent
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
return fileType;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Private method to parse the insert/update response and assign FileUploader to file type columns
|
|
512
|
+
* @param resp
|
|
513
|
+
* @param fileTypes
|
|
514
|
+
*
|
|
515
|
+
* @internal
|
|
516
|
+
*/
|
|
517
|
+
parseResponse(resp, fileTypes) {
|
|
518
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
519
|
+
fileTypes.forEach((obj) => __awaiter(this, void 0, void 0, function* () {
|
|
520
|
+
const fileResp = resp[obj.apiName];
|
|
521
|
+
resp[obj.apiName] = new FileUploader(this._client, this.viewId, fileResp.uploadUrl, fileResp.metafest.fileQid, resp.$qid);
|
|
522
|
+
if (obj.file instanceof Blob) {
|
|
523
|
+
yield resp[obj.apiName].Upload(obj.file);
|
|
524
|
+
resp[obj.apiName] = fileResp.metafest;
|
|
525
|
+
}
|
|
526
|
+
}));
|
|
527
|
+
return resp;
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Add data to list object in insertInBulk.
|
|
532
|
+
*
|
|
533
|
+
* @param data array of object representing the data
|
|
534
|
+
*
|
|
535
|
+
* @category ListObject
|
|
536
|
+
*/
|
|
537
|
+
insertInBulk(data, offlineOptions) {
|
|
538
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
539
|
+
let url = this.dataUrl();
|
|
540
|
+
url += '/import';
|
|
541
|
+
const [res, err] = yield this._client.put(url, data, offlineOptions, {
|
|
542
|
+
headers: { 'Content-Type': 'application/json' },
|
|
543
|
+
});
|
|
544
|
+
if (err) {
|
|
545
|
+
err.setMessage(`failed to insert bulk data: ${err.message}`);
|
|
546
|
+
throw err;
|
|
547
|
+
}
|
|
548
|
+
return res;
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Update an existing record on the list type object
|
|
553
|
+
*
|
|
554
|
+
* @param data An object representing the data. The QID of the record is required in the data object
|
|
555
|
+
*
|
|
556
|
+
* @category ListObject
|
|
557
|
+
*/
|
|
558
|
+
update(data, offlineOptions) {
|
|
559
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
560
|
+
const url = this.dataUrl();
|
|
561
|
+
const fileTypes = this.parseForSpecialTypes(data);
|
|
562
|
+
const [res, err] = yield this._client.put(url, data, offlineOptions, {
|
|
563
|
+
headers: { 'Content-Type': 'application/json' },
|
|
564
|
+
});
|
|
565
|
+
if (err) {
|
|
566
|
+
err.setMessage(`failed to update data: ${err.message}`);
|
|
567
|
+
throw err;
|
|
568
|
+
}
|
|
569
|
+
return this.parseResponse(res, fileTypes);
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Delete a record in the list object.
|
|
574
|
+
*
|
|
575
|
+
* @param id ID value of the record
|
|
576
|
+
*
|
|
577
|
+
* @category ListObject
|
|
578
|
+
*/
|
|
579
|
+
delete(id, dataScope = '', offlineOptions) {
|
|
580
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
581
|
+
const url = this.dataUrl();
|
|
582
|
+
const req = {
|
|
583
|
+
id: id,
|
|
584
|
+
$dataScope: dataScope
|
|
585
|
+
};
|
|
586
|
+
const [, err] = yield this._client.delete(url, req, offlineOptions, {
|
|
587
|
+
headers: { 'Content-Type': 'application/json' },
|
|
588
|
+
});
|
|
589
|
+
if (err) {
|
|
590
|
+
err.setMessage(`failed to delete data: ${err.message}`);
|
|
591
|
+
throw err;
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Get a record from list object using a filter.
|
|
597
|
+
* Example:
|
|
598
|
+
* ```js
|
|
599
|
+
* let f: Filter = {
|
|
600
|
+
* "strCol": "test",
|
|
601
|
+
* "numCol":{
|
|
602
|
+
* lt: 10
|
|
603
|
+
* }
|
|
604
|
+
* }
|
|
605
|
+
* let res = await obj.match(f)
|
|
606
|
+
* ```
|
|
607
|
+
*
|
|
608
|
+
* Above input will filter "strCol" for "test" and "numCol" for values less than 10
|
|
609
|
+
*
|
|
610
|
+
* @param filter: {@link Filter}
|
|
611
|
+
* @param lang: optional language value. Allowed inputs are "all" or any language defined in project languages. If no value is passed, then project's default language will be used for returning data
|
|
612
|
+
* @category ListObject
|
|
613
|
+
*/
|
|
614
|
+
match(f, lang) {
|
|
615
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
616
|
+
const filterQueryArg = this.getFilterQuery(f);
|
|
617
|
+
let url = '';
|
|
618
|
+
if (this._useCaching) {
|
|
619
|
+
if (this.viewId === '') {
|
|
620
|
+
url = `${environment.cachingHost}/data/${this.objectApiName}?withSDFileURL=false&schemaScope=${this._projectId}${filterQueryArg}`;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
url = `${environment.cachingHost}/api/v1/views/${this.viewId}/data/${this.objectApiName}?withSDFileURL=false&${filterQueryArg}`;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
url = this.dataUrl(null, filterQueryArg) + '&withSDFileURL=false';
|
|
628
|
+
}
|
|
629
|
+
url += lang
|
|
630
|
+
? `${url.indexOf('?') < 0 ? '?' : '&'}language=${lang === 'all' ? '*' : lang}`
|
|
631
|
+
: '';
|
|
632
|
+
const [res, err] = yield this._client.get(url);
|
|
633
|
+
if (err) {
|
|
634
|
+
err.setMessage('failed to get data');
|
|
635
|
+
throw err;
|
|
636
|
+
}
|
|
637
|
+
return Parser.parseSpecialTypes(res);
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
getFile(instanceQID, fileQID, forceDownload = false) {
|
|
641
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
642
|
+
let url = this.dataUrl(instanceQID);
|
|
643
|
+
url += '/files/' + fileQID;
|
|
644
|
+
if (forceDownload) {
|
|
645
|
+
url += '?forcedownload=' + forceDownload;
|
|
646
|
+
}
|
|
647
|
+
const [res, err] = yield this._client.get(url);
|
|
648
|
+
if (err) {
|
|
649
|
+
err.setMessage(`failed to get data: ${err.message}`);
|
|
650
|
+
throw err;
|
|
651
|
+
}
|
|
652
|
+
return res;
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Private method to get filter query for match method.
|
|
657
|
+
*
|
|
658
|
+
* @param Filter
|
|
659
|
+
*
|
|
660
|
+
* @internal
|
|
661
|
+
*/
|
|
662
|
+
getFilterQuery(f) {
|
|
663
|
+
let filterPredicate = '';
|
|
664
|
+
if (f != null) {
|
|
665
|
+
for (const [objName, objectsData] of Object.entries(f)) {
|
|
666
|
+
if (typeof objectsData === 'object') {
|
|
667
|
+
const fe = objectsData;
|
|
668
|
+
filterPredicate += fe.gt
|
|
669
|
+
? this.getFilterValue(objName, fe.gt, '>')
|
|
670
|
+
: '';
|
|
671
|
+
filterPredicate += fe.lt
|
|
672
|
+
? this.getFilterValue(objName, fe.lt, '<')
|
|
673
|
+
: '';
|
|
674
|
+
filterPredicate += fe.gte
|
|
675
|
+
? this.getFilterValue(objName, fe.gte, '>=')
|
|
676
|
+
: '';
|
|
677
|
+
filterPredicate += fe.lte
|
|
678
|
+
? this.getFilterValue(objName, fe.lte, '<=')
|
|
679
|
+
: '';
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
filterPredicate += `&filter=${objName}=${encodeURIComponent(this.handleTypes(objectsData))}`;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return filterPredicate;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Private method to get create filter string.
|
|
690
|
+
* @param objName
|
|
691
|
+
* @param input
|
|
692
|
+
* @param op
|
|
693
|
+
* @internal
|
|
694
|
+
*/
|
|
695
|
+
getFilterValue(objName, input, op) {
|
|
696
|
+
const v = this.handleTypes(input);
|
|
697
|
+
if (v) {
|
|
698
|
+
console.log("_________ getfilter ??? ", `&filter=${objName}${op}${encodeURIComponent(v)}`);
|
|
699
|
+
return `&filter=${objName}${op}${encodeURIComponent(v)}`;
|
|
700
|
+
}
|
|
701
|
+
return '';
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Private method to handle different types.
|
|
705
|
+
* @param input
|
|
706
|
+
* @internal
|
|
707
|
+
*/
|
|
708
|
+
handleTypes(input) {
|
|
709
|
+
switch (typeof input) {
|
|
710
|
+
case 'string':
|
|
711
|
+
case 'number': {
|
|
712
|
+
return input;
|
|
713
|
+
}
|
|
714
|
+
default: {
|
|
715
|
+
if (input instanceof Date) {
|
|
716
|
+
return input.toISOString().replace('T', '%20').replace('Z', '');
|
|
717
|
+
}
|
|
718
|
+
return '';
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Private method to form the url.
|
|
724
|
+
*
|
|
725
|
+
* @param instanceId
|
|
726
|
+
*
|
|
727
|
+
* @internal
|
|
728
|
+
*/
|
|
729
|
+
dataUrl(instanceId, fp) {
|
|
730
|
+
let url = '';
|
|
731
|
+
if (this.viewId === '') {
|
|
732
|
+
url = environment.adminHost + '/api/v1/data/' + this.objectApiName;
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
url =
|
|
736
|
+
environment.host +
|
|
737
|
+
'/api/v1/views/' +
|
|
738
|
+
this.viewId +
|
|
739
|
+
'/data/' +
|
|
740
|
+
this.objectApiName;
|
|
741
|
+
}
|
|
742
|
+
if (instanceId) {
|
|
743
|
+
url += '/' + instanceId;
|
|
744
|
+
}
|
|
745
|
+
if (fp) {
|
|
746
|
+
url += `?${fp}`;
|
|
747
|
+
}
|
|
748
|
+
return url;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* A epsilon class to execute the epsilon
|
|
754
|
+
*/
|
|
755
|
+
class Epsilon {
|
|
756
|
+
/**
|
|
757
|
+
* Construct epsilon with viewId, client, host and adminHost.
|
|
758
|
+
*
|
|
759
|
+
* @param viewId
|
|
760
|
+
* @param client
|
|
761
|
+
*
|
|
762
|
+
* @internal
|
|
763
|
+
*/
|
|
764
|
+
constructor(viewId, client) {
|
|
765
|
+
this.viewId = viewId;
|
|
766
|
+
this._client = client;
|
|
767
|
+
}
|
|
768
|
+
setDefaults() {
|
|
769
|
+
var _a;
|
|
770
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
771
|
+
if (!this.view) {
|
|
772
|
+
this.view = new View(this.viewId);
|
|
773
|
+
}
|
|
774
|
+
if (!this.folders || ((_a = this.folders) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
775
|
+
this.folders = yield this.view.list();
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Execute an epsilon.
|
|
781
|
+
*
|
|
782
|
+
* @param fileName name of epsilon file.
|
|
783
|
+
* @param requestOptions object
|
|
784
|
+
* @param offlineOptions object of type OfflineOptions (optional)
|
|
785
|
+
*
|
|
786
|
+
*/
|
|
787
|
+
execute(fileName, requestOptions, offlineOptions) {
|
|
788
|
+
var _a;
|
|
789
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
790
|
+
const url = yield this.getEpsilonFileURL(fileName);
|
|
791
|
+
const headers = new Headers(requestOptions.headers);
|
|
792
|
+
const data = yield ((_a = this.view) === null || _a === void 0 ? void 0 : _a.data());
|
|
793
|
+
headers.append('Authorization', 'Bearer ' + data.authToken);
|
|
794
|
+
headers.append('Content-Type', 'application/json');
|
|
795
|
+
const request = {
|
|
796
|
+
method: 'POST',
|
|
797
|
+
headers: headers,
|
|
798
|
+
redirect: 'follow',
|
|
799
|
+
body: JSON.stringify(requestOptions),
|
|
800
|
+
};
|
|
801
|
+
let __offlineOptions = offlineOptions;
|
|
802
|
+
if (!__offlineOptions) {
|
|
803
|
+
__offlineOptions = {
|
|
804
|
+
offlineAction: requestOptions.action || 'No title',
|
|
805
|
+
disabled: true
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
const [res, err] = yield this._client.do(url, request, __offlineOptions);
|
|
809
|
+
if (err) {
|
|
810
|
+
err.setMessage(`failed to execute epsilon: ${err.message}`);
|
|
811
|
+
throw err;
|
|
812
|
+
}
|
|
813
|
+
return res;
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
getEpsilonFileURL(fileName) {
|
|
817
|
+
var _a, _b;
|
|
818
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
819
|
+
if (!this.folders || ((_a = this.folders) === null || _a === void 0 ? void 0 : _a.length) === 0)
|
|
820
|
+
yield this.setDefaults();
|
|
821
|
+
const virtualFile = (_b = this.folders) === null || _b === void 0 ? void 0 : _b.filter((result) => {
|
|
822
|
+
return result.Name === fileName;
|
|
823
|
+
});
|
|
824
|
+
if (virtualFile && virtualFile[0])
|
|
825
|
+
return (environment.host +
|
|
826
|
+
'/api/v1/views/' +
|
|
827
|
+
virtualFile[0].TemplateBagId +
|
|
828
|
+
'/files/' +
|
|
829
|
+
virtualFile[0].FileQid);
|
|
830
|
+
return '';
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
class TwintagBase {
|
|
836
|
+
constructor(qid) {
|
|
837
|
+
this._useCaching = false;
|
|
838
|
+
this._qid = qid;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* set caching host
|
|
842
|
+
* @param val
|
|
843
|
+
* @hidden
|
|
844
|
+
*/
|
|
845
|
+
useCaching(val) {
|
|
846
|
+
this._useCaching = val;
|
|
847
|
+
}
|
|
848
|
+
viewURL() {
|
|
849
|
+
return environment.host + '/api/v1/views/' + this._qid;
|
|
850
|
+
}
|
|
851
|
+
twintagURL() {
|
|
852
|
+
return environment.host + '/api/v1/twintags/' + this._data.bagQid;
|
|
853
|
+
}
|
|
854
|
+
setconfig(init) {
|
|
855
|
+
this._client = init.client;
|
|
856
|
+
this._data = init.data;
|
|
857
|
+
this._project = init.project;
|
|
858
|
+
}
|
|
859
|
+
client() {
|
|
860
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
861
|
+
if (!this._client) {
|
|
862
|
+
this._client = new Client();
|
|
863
|
+
}
|
|
864
|
+
if (!this._client.token) {
|
|
865
|
+
const data = yield this.data();
|
|
866
|
+
this.setToken(data.authToken);
|
|
867
|
+
}
|
|
868
|
+
return this._client;
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Set the token used for authorization. This can be used to authorize
|
|
873
|
+
* requests by the project API key rather than the view QID. However,
|
|
874
|
+
* It is recommended use the {@link Project} object instead.
|
|
875
|
+
*/
|
|
876
|
+
setToken(token) {
|
|
877
|
+
if (!this._client) {
|
|
878
|
+
this._client = new Client();
|
|
879
|
+
}
|
|
880
|
+
this._client.token = token;
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Data gets the view definition. This includes the view rights.
|
|
884
|
+
*/
|
|
885
|
+
data() {
|
|
886
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
887
|
+
const data = this._data;
|
|
888
|
+
if (data) {
|
|
889
|
+
return data;
|
|
890
|
+
}
|
|
891
|
+
let client = this._client;
|
|
892
|
+
if (!client) {
|
|
893
|
+
client = new Client();
|
|
894
|
+
this._client = client;
|
|
895
|
+
}
|
|
896
|
+
const [newData, err] = yield client.get(environment.host + '/api/v1/views/' + this._qid);
|
|
897
|
+
if (err) {
|
|
898
|
+
err.setMessage(`failed to get twintag data`);
|
|
899
|
+
throw err;
|
|
900
|
+
}
|
|
901
|
+
this._data = newData;
|
|
902
|
+
return this._data;
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* CreateBag creates a free bag without an association to an Enterprise project.
|
|
909
|
+
*/
|
|
910
|
+
function createBag(qid) {
|
|
911
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
912
|
+
return createBagInternal(new Client(), undefined, qid);
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* CreateBagInternal is the internal createBag function.
|
|
917
|
+
*
|
|
918
|
+
* @internal */
|
|
919
|
+
function createBagInternal(client, project, qid) {
|
|
920
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
921
|
+
let viewReq;
|
|
922
|
+
if (qid && qid !== '') {
|
|
923
|
+
viewReq = {
|
|
924
|
+
id: qid,
|
|
925
|
+
type: 'user',
|
|
926
|
+
data: {
|
|
927
|
+
rights: ['read', 'list'],
|
|
928
|
+
isCanocical: 1,
|
|
929
|
+
},
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
viewReq = {
|
|
934
|
+
type: 'owner',
|
|
935
|
+
data: undefined,
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
const path = environment.host + '/api/v1/views';
|
|
939
|
+
const [data, err] = yield client.put(path, viewReq);
|
|
940
|
+
if (err) {
|
|
941
|
+
err.setMessage(`failed to create a twintag`);
|
|
942
|
+
throw err;
|
|
943
|
+
}
|
|
944
|
+
const view = new View(data.id);
|
|
945
|
+
// Pass state
|
|
946
|
+
view._setConfig({ project: project, client: client, data: data });
|
|
947
|
+
return view;
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* The view class allows you to interact with a view into a bag.
|
|
952
|
+
* A view is represented by a `qid`. This is the string you see in its url:
|
|
953
|
+
* `https://twintag.io/<qid>`.
|
|
954
|
+
* A bag can have multiple views, each view can have different rights associated.
|
|
955
|
+
* For example: owner, download-only, upload-only, ...
|
|
956
|
+
*
|
|
957
|
+
* To construct a view object, you pass its QID, E.g.:
|
|
958
|
+
* ```
|
|
959
|
+
* let view = new Twintag.View(viewId)
|
|
960
|
+
* ```
|
|
961
|
+
*/
|
|
962
|
+
class View {
|
|
963
|
+
/**
|
|
964
|
+
* Construct a view by its QID.
|
|
965
|
+
*
|
|
966
|
+
* @param init Internal parameter.
|
|
967
|
+
*/
|
|
968
|
+
constructor(qid) {
|
|
969
|
+
this._base = new TwintagBase(qid);
|
|
970
|
+
}
|
|
971
|
+
get qid() {
|
|
972
|
+
return this._base._qid;
|
|
973
|
+
}
|
|
974
|
+
set qid(val) {
|
|
975
|
+
this._base._qid = val;
|
|
976
|
+
}
|
|
977
|
+
get _client() {
|
|
978
|
+
return this._base._client;
|
|
979
|
+
}
|
|
980
|
+
set _client(val) {
|
|
981
|
+
this._base._client = val;
|
|
982
|
+
}
|
|
983
|
+
get _data() {
|
|
984
|
+
return this._base._data;
|
|
985
|
+
}
|
|
986
|
+
set _data(val) {
|
|
987
|
+
this._base._data = val;
|
|
988
|
+
}
|
|
989
|
+
get project() {
|
|
990
|
+
return this._base._project;
|
|
991
|
+
}
|
|
992
|
+
set project(val) {
|
|
993
|
+
this._base._project = val;
|
|
994
|
+
}
|
|
995
|
+
useCaching(val) {
|
|
996
|
+
this._base._useCaching = val;
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* _setConfig allows us to pass internal state.
|
|
1000
|
+
*
|
|
1001
|
+
* @internal */
|
|
1002
|
+
_setConfig(init) {
|
|
1003
|
+
this._base.setconfig(init);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Set the token used for authorization. This can be used to authorize
|
|
1007
|
+
* requests by the project API key rather than the view QID. However,
|
|
1008
|
+
* It is recommended use the {@link Project} object instead.
|
|
1009
|
+
*/
|
|
1010
|
+
setToken(token) {
|
|
1011
|
+
this._base.setToken(token);
|
|
1012
|
+
}
|
|
1013
|
+
fileURL(obj, qid, op, useCachingHost = false) {
|
|
1014
|
+
let url = (useCachingHost && this._base._useCaching ? environment.cachingHost : environment.host) + '/api/v1/views/' + this._base._qid + '/' + obj;
|
|
1015
|
+
if (qid) {
|
|
1016
|
+
url += '/' + qid;
|
|
1017
|
+
}
|
|
1018
|
+
if (op) {
|
|
1019
|
+
url += '/' + op;
|
|
1020
|
+
}
|
|
1021
|
+
return url;
|
|
1022
|
+
}
|
|
1023
|
+
fileURLUpload(obj, qid, op) {
|
|
1024
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1025
|
+
const data = yield this._base.data();
|
|
1026
|
+
let url = this.fileURL(obj, qid, op);
|
|
1027
|
+
if (data.uploadsession) {
|
|
1028
|
+
url += '?uploadsession=' + data.uploadsession;
|
|
1029
|
+
}
|
|
1030
|
+
return url;
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Data gets the view definition. This includes the view rights.
|
|
1035
|
+
*/
|
|
1036
|
+
data() {
|
|
1037
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1038
|
+
return yield this._base.data();
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Upload allows you to upload a file into a bag.
|
|
1043
|
+
*
|
|
1044
|
+
* Required rights: upload.
|
|
1045
|
+
*
|
|
1046
|
+
* @param name Optionally overwrite the file name.
|
|
1047
|
+
* @param parent: parent of the file. FileQid of the folder
|
|
1048
|
+
*
|
|
1049
|
+
* @category File management
|
|
1050
|
+
*/
|
|
1051
|
+
upload(f, name, parent) {
|
|
1052
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1053
|
+
// Start
|
|
1054
|
+
const uploadStartReq = {
|
|
1055
|
+
mode: 420,
|
|
1056
|
+
name: name ? name : f.name,
|
|
1057
|
+
size: f.size,
|
|
1058
|
+
parent: parent ? parent : null
|
|
1059
|
+
};
|
|
1060
|
+
let url = yield this.fileURLUpload('files');
|
|
1061
|
+
const client = yield this._base.client();
|
|
1062
|
+
const [startResp, startErr] = yield client.put(url, uploadStartReq);
|
|
1063
|
+
if (startErr) {
|
|
1064
|
+
startErr.setMessage(`failed to start upload file to twintag`);
|
|
1065
|
+
throw startErr;
|
|
1066
|
+
}
|
|
1067
|
+
// Upload
|
|
1068
|
+
const [, uploadErr] = yield client.do(startResp.uploadUrl, { method: 'PUT', body: f }, explicitDisableOffline, true, true);
|
|
1069
|
+
if (uploadErr) {
|
|
1070
|
+
uploadErr.setMessage(`failed to upload file to twintag`);
|
|
1071
|
+
throw uploadErr;
|
|
1072
|
+
}
|
|
1073
|
+
// End
|
|
1074
|
+
url = yield this.fileURLUpload('files', startResp.metafest.fileQid, 'end');
|
|
1075
|
+
const [, endErr] = yield client.do(url, { method: 'PUT', body: '{}' }, explicitDisableOffline, true);
|
|
1076
|
+
if (endErr) {
|
|
1077
|
+
endErr.setMessage(`failed to complete the file upload to twintag`);
|
|
1078
|
+
throw endErr;
|
|
1079
|
+
}
|
|
1080
|
+
const fileInfo = {
|
|
1081
|
+
FileQid: startResp.metafest.fileQid,
|
|
1082
|
+
Name: startResp.metafest.fileName,
|
|
1083
|
+
Parent: undefined,
|
|
1084
|
+
Size: startResp.metafest.size,
|
|
1085
|
+
MTime: startResp.metafest.modTime,
|
|
1086
|
+
FileMode: startResp.metafest.fileMode.toString(),
|
|
1087
|
+
};
|
|
1088
|
+
return fileInfo;
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Upload a {@VirtualFile | virtual file} into a bag.
|
|
1093
|
+
*
|
|
1094
|
+
* Required rights: owner.
|
|
1095
|
+
*
|
|
1096
|
+
* @category File management
|
|
1097
|
+
*/
|
|
1098
|
+
uploadVirtual(f, name) {
|
|
1099
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1100
|
+
const uploadReq = {
|
|
1101
|
+
mode: f.mode,
|
|
1102
|
+
name: name,
|
|
1103
|
+
size: 0,
|
|
1104
|
+
fileContent: f.GetDefinition(),
|
|
1105
|
+
};
|
|
1106
|
+
const url = yield this.fileURLUpload('virtual');
|
|
1107
|
+
const client = yield this._base.client();
|
|
1108
|
+
const [, err] = yield client.put(url, uploadReq, explicitDisableOffline, {}, true);
|
|
1109
|
+
if (err) {
|
|
1110
|
+
err.setMessage(`failed to upload virtual file to twintag`);
|
|
1111
|
+
throw err;
|
|
1112
|
+
}
|
|
1113
|
+
// TODO: Parse FileInfo in response
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Download a file from a bag.
|
|
1118
|
+
*
|
|
1119
|
+
* Required rights: download.
|
|
1120
|
+
*
|
|
1121
|
+
* @category File management
|
|
1122
|
+
*/
|
|
1123
|
+
download(name) {
|
|
1124
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1125
|
+
// TODO: support name & fileInfo
|
|
1126
|
+
const url = this.fileURL('web', name);
|
|
1127
|
+
const client = yield this._base.client();
|
|
1128
|
+
const [res, err] = yield client.do(url, { method: 'get', headers: { 'Content-Type': 'application/octet-stream' } }, explicitDisableOffline, true, true);
|
|
1129
|
+
if (err) {
|
|
1130
|
+
err.setMessage(`failed to download file from twintag`);
|
|
1131
|
+
throw err;
|
|
1132
|
+
}
|
|
1133
|
+
return res;
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Convenience method to download a JSON file from a bag and parse it.
|
|
1138
|
+
*
|
|
1139
|
+
* Required rights: download.
|
|
1140
|
+
*
|
|
1141
|
+
* @category File management
|
|
1142
|
+
*/
|
|
1143
|
+
downloadJSON(name) {
|
|
1144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1145
|
+
// TODO: support name & fileInfo
|
|
1146
|
+
const url = this.fileURL('web', name);
|
|
1147
|
+
const client = yield this._base.client();
|
|
1148
|
+
const [res, err] = yield client.get(url, explicitDisableOffline, { headers: { 'Content-Type': 'application/json' } }, true);
|
|
1149
|
+
if (err) {
|
|
1150
|
+
err.setMessage(`failed to downlaod JSON file from twintag`);
|
|
1151
|
+
throw err;
|
|
1152
|
+
}
|
|
1153
|
+
return res;
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Rename a file from a bag.
|
|
1158
|
+
*
|
|
1159
|
+
* Required rights: upload & download.
|
|
1160
|
+
*
|
|
1161
|
+
* @category File management
|
|
1162
|
+
*/
|
|
1163
|
+
rename(source, name) {
|
|
1164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1165
|
+
return yield this.doMove(source, name, undefined, undefined, false);
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Move a file.
|
|
1170
|
+
*
|
|
1171
|
+
* Required rights: upload & download, plus owner rights when specifying a bag.
|
|
1172
|
+
*
|
|
1173
|
+
* @category File management
|
|
1174
|
+
*/
|
|
1175
|
+
move(source, name, parent, view) {
|
|
1176
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1177
|
+
return yield this.doMove(source, name, parent, view, false);
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Copy a file.
|
|
1182
|
+
*
|
|
1183
|
+
* Required rights: upload & download, plus owner rights when specifying a bag.
|
|
1184
|
+
*
|
|
1185
|
+
* @category File management
|
|
1186
|
+
*/
|
|
1187
|
+
copy(source, name, parent, view) {
|
|
1188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1189
|
+
return yield this.doMove(source, name, parent, view, true);
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
doMove(source, name, parent, view, copy) {
|
|
1193
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1194
|
+
// TODO: implementation
|
|
1195
|
+
if (parent === undefined)
|
|
1196
|
+
parent = '';
|
|
1197
|
+
if (view === undefined)
|
|
1198
|
+
view = '';
|
|
1199
|
+
if (name === undefined)
|
|
1200
|
+
name = '';
|
|
1201
|
+
if (copy === undefined)
|
|
1202
|
+
copy = false;
|
|
1203
|
+
const url = this.fileURL('files/' + source.FileQid + '/move');
|
|
1204
|
+
const fileMoveRequest = {
|
|
1205
|
+
fileQid: source.FileQid,
|
|
1206
|
+
targetBag: view,
|
|
1207
|
+
targetFolder: parent,
|
|
1208
|
+
targetName: name,
|
|
1209
|
+
isCopy: copy,
|
|
1210
|
+
};
|
|
1211
|
+
const client = yield this._base.client();
|
|
1212
|
+
const [resp, err] = yield client.put(url, fileMoveRequest);
|
|
1213
|
+
if (err) {
|
|
1214
|
+
err.setMessage(`failed to move file in twintag`);
|
|
1215
|
+
throw err;
|
|
1216
|
+
}
|
|
1217
|
+
return resp;
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Delete a file from a bag.
|
|
1222
|
+
*
|
|
1223
|
+
* Required rights: delete.
|
|
1224
|
+
*
|
|
1225
|
+
* @category File management
|
|
1226
|
+
*/
|
|
1227
|
+
delete(file) {
|
|
1228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1229
|
+
// TODO: support filename; filename[], FileInfo & fileInfo[]
|
|
1230
|
+
const url = this.fileURL('files');
|
|
1231
|
+
const client = yield this._base.client();
|
|
1232
|
+
const [, err] = yield client.delete(url, [file.FileQid.toString()]);
|
|
1233
|
+
if (err) {
|
|
1234
|
+
err.setMessage(`failed to delete file from twintag`);
|
|
1235
|
+
throw err;
|
|
1236
|
+
}
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Delete an entire bag.
|
|
1241
|
+
*
|
|
1242
|
+
* Required rights: owner.
|
|
1243
|
+
*/
|
|
1244
|
+
deleteBag() {
|
|
1245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1246
|
+
const url = this._base.viewURL();
|
|
1247
|
+
const client = yield this._base.client();
|
|
1248
|
+
const [, err] = yield client.delete(url);
|
|
1249
|
+
if (err) {
|
|
1250
|
+
err.setMessage(`failed to delete twintag`);
|
|
1251
|
+
throw err;
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Get a view with limited rights.
|
|
1257
|
+
*
|
|
1258
|
+
* Required rights: owner.
|
|
1259
|
+
*/
|
|
1260
|
+
getUserView(rights) {
|
|
1261
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1262
|
+
const url = environment.host + '/api/v1/views';
|
|
1263
|
+
if (!this._base._data) {
|
|
1264
|
+
yield this._base.data();
|
|
1265
|
+
}
|
|
1266
|
+
const viewReq = {
|
|
1267
|
+
id: undefined,
|
|
1268
|
+
type: 'user',
|
|
1269
|
+
data: {
|
|
1270
|
+
ownerId: this._base._qid,
|
|
1271
|
+
rights: rights,
|
|
1272
|
+
isCanocical: 1,
|
|
1273
|
+
},
|
|
1274
|
+
bagStorageQid: this._base._data.bagQid
|
|
1275
|
+
};
|
|
1276
|
+
const client = yield this._base.client();
|
|
1277
|
+
const [data, err] = yield client.put(url, viewReq);
|
|
1278
|
+
if (err) {
|
|
1279
|
+
err.setMessage(`failed to get view information`);
|
|
1280
|
+
throw err;
|
|
1281
|
+
}
|
|
1282
|
+
const userView = new View(data.id);
|
|
1283
|
+
// Pass state
|
|
1284
|
+
userView._setConfig({ project: this._base._project, data: data });
|
|
1285
|
+
return userView;
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* List the files in the bag or a sub-folder.
|
|
1290
|
+
*
|
|
1291
|
+
* Required rights: list.
|
|
1292
|
+
*
|
|
1293
|
+
* @category File management
|
|
1294
|
+
*/
|
|
1295
|
+
list(folder) {
|
|
1296
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1297
|
+
// TODO: support path
|
|
1298
|
+
const url = this.fileURL('folders', folder);
|
|
1299
|
+
const client = yield this._base.client();
|
|
1300
|
+
const [res, err] = yield client.get(url);
|
|
1301
|
+
if (err) {
|
|
1302
|
+
err.setMessage(`failed to get list of files from twintag`);
|
|
1303
|
+
throw err;
|
|
1304
|
+
}
|
|
1305
|
+
return res;
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* This method creates a folder for a twintag.
|
|
1310
|
+
* @param folderName
|
|
1311
|
+
* @param folderParent
|
|
1312
|
+
* @returns
|
|
1313
|
+
*/
|
|
1314
|
+
addFolder(folderName, folderParent) {
|
|
1315
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1316
|
+
if (folderName.trim().length === 0) {
|
|
1317
|
+
throw new Error("Invalid folder name.");
|
|
1318
|
+
}
|
|
1319
|
+
const url = this.fileURL('folders');
|
|
1320
|
+
const body = {
|
|
1321
|
+
name: folderName,
|
|
1322
|
+
parent: folderParent ? folderParent : null
|
|
1323
|
+
};
|
|
1324
|
+
const client = yield this._base.client();
|
|
1325
|
+
const [res, err] = yield client.put(url, body);
|
|
1326
|
+
if (err) {
|
|
1327
|
+
err.setMessage(`failed to create folder: ${err.message}`);
|
|
1328
|
+
throw err;
|
|
1329
|
+
}
|
|
1330
|
+
return res;
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Seal the bag.
|
|
1335
|
+
*
|
|
1336
|
+
* Required rights: list.
|
|
1337
|
+
*
|
|
1338
|
+
* @hidden
|
|
1339
|
+
*/
|
|
1340
|
+
seal() {
|
|
1341
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1342
|
+
const url = this.fileURL('seal');
|
|
1343
|
+
const client = yield this._base.client();
|
|
1344
|
+
const [, err] = yield client.put(url, {});
|
|
1345
|
+
if (err) {
|
|
1346
|
+
err.setMessage(`failed to seal`);
|
|
1347
|
+
throw err;
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Get the bag metadata of this specific bag. The metadata is returned as an object.
|
|
1353
|
+
*
|
|
1354
|
+
* Required rights: download.
|
|
1355
|
+
*
|
|
1356
|
+
* @param lang: optional language value. Allowed inputs are "all" or any language defined in project languages. If no value is passed, then project's default language will be used for returning data
|
|
1357
|
+
* @category Metadata
|
|
1358
|
+
*/
|
|
1359
|
+
getMetadata(lang) {
|
|
1360
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1361
|
+
let url = this.fileURL('data/metadata', undefined, undefined, true);
|
|
1362
|
+
url += lang ? `?language=${(lang === 'all' ? '*' : lang)}` : '';
|
|
1363
|
+
const client = yield this._base.client();
|
|
1364
|
+
const [res, err] = yield client.get(url);
|
|
1365
|
+
if (err) {
|
|
1366
|
+
err.setMessage(`failed to get metadata of twintag`);
|
|
1367
|
+
throw err;
|
|
1368
|
+
}
|
|
1369
|
+
return Parser.parseSpecialTypes(res);
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Set the bag metadata of this specific bag. Returns a full view of the resulting metadata.
|
|
1374
|
+
*
|
|
1375
|
+
* Required rights: owner.
|
|
1376
|
+
*
|
|
1377
|
+
* @param data An object representing the metadata.
|
|
1378
|
+
*
|
|
1379
|
+
* @category Metadata
|
|
1380
|
+
*/
|
|
1381
|
+
setMetadata(data) {
|
|
1382
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1383
|
+
const url = this.fileURL('data/metadata');
|
|
1384
|
+
const client = yield this._base.client();
|
|
1385
|
+
const [res, err] = yield client.put(url, data, explicitDisableOffline, { headers: { 'Content-Type': 'application/json' } });
|
|
1386
|
+
if (err) {
|
|
1387
|
+
err.setMessage(`failed to set metadata to twintag`);
|
|
1388
|
+
throw err;
|
|
1389
|
+
}
|
|
1390
|
+
return res;
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Get the bag data of a specific bag and object. The data is returned as an object.
|
|
1395
|
+
*
|
|
1396
|
+
* Required rights: download.
|
|
1397
|
+
*
|
|
1398
|
+
* @param objectAPIName The apiName of the object for which the data is being requested
|
|
1399
|
+
*
|
|
1400
|
+
* @param attribute Optional parameter to specify the attribute for which the data is required
|
|
1401
|
+
*
|
|
1402
|
+
* @category Structured Data
|
|
1403
|
+
*/
|
|
1404
|
+
getData(objectAPIName, attribute) {
|
|
1405
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1406
|
+
let url = this.fileURL('data/' + objectAPIName, undefined, undefined, true);
|
|
1407
|
+
if (attribute && attribute !== '') {
|
|
1408
|
+
url = url + '?property=' + attribute;
|
|
1409
|
+
}
|
|
1410
|
+
const client = yield this._base.client();
|
|
1411
|
+
const [res, err] = yield client.get(url);
|
|
1412
|
+
if (err) {
|
|
1413
|
+
err.setMessage(`failed to get data to twintag object: ${objectAPIName}`);
|
|
1414
|
+
throw err;
|
|
1415
|
+
}
|
|
1416
|
+
return Parser.parseSpecialTypes(res);
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Set the bag data of this specific bag and object. Returns a full view of the resulting data.
|
|
1421
|
+
*
|
|
1422
|
+
* Required rights: owner.
|
|
1423
|
+
*
|
|
1424
|
+
* @param data An object representing the data.
|
|
1425
|
+
* @param objectApiName APIName of the object for which the data is being set.
|
|
1426
|
+
*
|
|
1427
|
+
* @category Structured Data
|
|
1428
|
+
*/
|
|
1429
|
+
setData(objectApiName, data) {
|
|
1430
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1431
|
+
const url = this.fileURL('data/' + objectApiName);
|
|
1432
|
+
const client = yield this._base.client();
|
|
1433
|
+
const [res, err] = yield client.put(url, data, explicitDisableOffline, { headers: { 'Content-Type': 'application/json' } });
|
|
1434
|
+
if (err) {
|
|
1435
|
+
err.setMessage(`failed to set data to twintag object: ${objectApiName}`);
|
|
1436
|
+
throw err;
|
|
1437
|
+
}
|
|
1438
|
+
return res;
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Get an object for the view
|
|
1443
|
+
*
|
|
1444
|
+
* Required rights: owner.
|
|
1445
|
+
*
|
|
1446
|
+
* @param objectApiName APIName of the object
|
|
1447
|
+
*
|
|
1448
|
+
* @category Structured Data
|
|
1449
|
+
*/
|
|
1450
|
+
object(objectApiName) {
|
|
1451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1452
|
+
const client = yield this._base.client();
|
|
1453
|
+
const data = yield this._base.data();
|
|
1454
|
+
if (!data.data.project || !data.data.project.projectId || data.data.project.projectId === '') {
|
|
1455
|
+
throw new Error(`view not tagged to any project`);
|
|
1456
|
+
}
|
|
1457
|
+
return new ListObject(objectApiName, client, data.id, '', this._base._useCaching);
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Sends notification to the registered users of the view.
|
|
1462
|
+
*
|
|
1463
|
+
* Required rights: owner.
|
|
1464
|
+
*
|
|
1465
|
+
* @param message message to be sent as a notification.
|
|
1466
|
+
* @param channel optional, if not specified then default channel is 'email'
|
|
1467
|
+
*
|
|
1468
|
+
* Example:
|
|
1469
|
+
* ```js
|
|
1470
|
+
* await viewObj.notify(`This is a custom email body.`)
|
|
1471
|
+
* ```
|
|
1472
|
+
*
|
|
1473
|
+
* You can further customize email body by passing {@link NotificationRequest}:
|
|
1474
|
+
* ```js
|
|
1475
|
+
* await viewObj.notify({
|
|
1476
|
+
* message: "custom user message"
|
|
1477
|
+
* subject: "custom email subject"
|
|
1478
|
+
* bagAlias: "Custom alias for bag"
|
|
1479
|
+
* showBagReport: true
|
|
1480
|
+
* language: "en-GB"
|
|
1481
|
+
* })
|
|
1482
|
+
* ```
|
|
1483
|
+
* You can provide any ISO 15897 locale for language attribute.
|
|
1484
|
+
* Currently supported values: en_GB, nl_BE, fr_BE
|
|
1485
|
+
* @category Notification
|
|
1486
|
+
*/
|
|
1487
|
+
notify(request, channel) {
|
|
1488
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1489
|
+
const client = yield this._base.client();
|
|
1490
|
+
let body;
|
|
1491
|
+
if (typeof request === 'string') {
|
|
1492
|
+
body = {
|
|
1493
|
+
message: request,
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
else {
|
|
1497
|
+
body = request;
|
|
1498
|
+
}
|
|
1499
|
+
channel = channel ? channel : 'email';
|
|
1500
|
+
const url = this._base.viewURL() + '/notification?type=' + channel;
|
|
1501
|
+
const [res, err] = yield client.post(url, body, { headers: { 'Content-Type': 'application/json' } });
|
|
1502
|
+
if (err) {
|
|
1503
|
+
err.setMessage('failed to notify to all subcribers of twintag');
|
|
1504
|
+
throw err;
|
|
1505
|
+
}
|
|
1506
|
+
return res;
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Sends email to the registered users of the view.
|
|
1511
|
+
*
|
|
1512
|
+
* @param request message to be sent.
|
|
1513
|
+
*
|
|
1514
|
+
* Example:
|
|
1515
|
+
* ```js
|
|
1516
|
+
* await viewObj.sendFeedback({content: 'This is test content'})
|
|
1517
|
+
* ```
|
|
1518
|
+
*
|
|
1519
|
+
* You can further customize email body by passing {@link FeedbackRequest}:
|
|
1520
|
+
* ```js
|
|
1521
|
+
* await viewObj.sendFeedback({
|
|
1522
|
+
* content: 'This is test content',
|
|
1523
|
+
* subject: "custom email subject",
|
|
1524
|
+
* email: 'email';
|
|
1525
|
+
* })
|
|
1526
|
+
* ```
|
|
1527
|
+
* @category Notification
|
|
1528
|
+
*/
|
|
1529
|
+
sendFeedback(request) {
|
|
1530
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1531
|
+
const client = yield this._base.client();
|
|
1532
|
+
let body;
|
|
1533
|
+
if (typeof request === 'string') {
|
|
1534
|
+
body = {
|
|
1535
|
+
content: request,
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
else {
|
|
1539
|
+
body = request;
|
|
1540
|
+
}
|
|
1541
|
+
const url = this._base.viewURL() + '/feedback';
|
|
1542
|
+
const [res, err] = yield client.put(url, body, explicitDisableOffline, { headers: { 'Content-Type': 'application/json' } });
|
|
1543
|
+
if (err) {
|
|
1544
|
+
err.setMessage(`failed to submit feedback`);
|
|
1545
|
+
throw err;
|
|
1546
|
+
}
|
|
1547
|
+
return res;
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Sends email
|
|
1552
|
+
*
|
|
1553
|
+
* Required rights: Any.
|
|
1554
|
+
*
|
|
1555
|
+
* @param request EmailRequest object
|
|
1556
|
+
*
|
|
1557
|
+
* Example:
|
|
1558
|
+
*
|
|
1559
|
+
* You can call this method by passing {@link EmailRequest}:
|
|
1560
|
+
* ```js
|
|
1561
|
+
* await viewObj.sendToSubscribers({
|
|
1562
|
+
* recepients: ["to@mail.com"]
|
|
1563
|
+
* body: "email body"
|
|
1564
|
+
* subject: "email subject"
|
|
1565
|
+
* cc: ["cc@mail.com"]
|
|
1566
|
+
* bcc: ["bcc@mail.com"]
|
|
1567
|
+
* })
|
|
1568
|
+
* ```
|
|
1569
|
+
* @category Notifications
|
|
1570
|
+
*/
|
|
1571
|
+
sendToSubscribers(request) {
|
|
1572
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1573
|
+
const client = yield this._base.client();
|
|
1574
|
+
yield this._base.data();
|
|
1575
|
+
const url = this._base.viewURL() + `/notification?type=customEmail`;
|
|
1576
|
+
const [res, err] = yield client.post(url, request, { headers: { 'Content-Type': 'application/json' } });
|
|
1577
|
+
if (err) {
|
|
1578
|
+
err.setMessage('failed to notify to all subcribers of twintag through custom email');
|
|
1579
|
+
throw err;
|
|
1580
|
+
}
|
|
1581
|
+
return res;
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Execute an epsilon.
|
|
1586
|
+
*
|
|
1587
|
+
* Required rights: any.
|
|
1588
|
+
*
|
|
1589
|
+
* @param filename name of epsilon file.
|
|
1590
|
+
* @param requestOptions object
|
|
1591
|
+
* @param action (optional) title/name of request for offline support
|
|
1592
|
+
*
|
|
1593
|
+
* @category Structured Data
|
|
1594
|
+
*/
|
|
1595
|
+
executeEpsilon(filename, requestOptions, offlineOptions) {
|
|
1596
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1597
|
+
if (!this._epsilon) {
|
|
1598
|
+
const client = yield this._base.client();
|
|
1599
|
+
const data = yield this.data();
|
|
1600
|
+
if (!data.data.project || !data.data.project.projectId || data.data.project.projectId === '') {
|
|
1601
|
+
throw new Error(`view not tagged to any project`);
|
|
1602
|
+
}
|
|
1603
|
+
this._epsilon = new Epsilon(data.id, client);
|
|
1604
|
+
}
|
|
1605
|
+
return yield this._epsilon.execute(filename, requestOptions, offlineOptions);
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* StructuredObject class represents an object of a project.
|
|
1612
|
+
* Operations like creating attributes, getting attributes can be informed.
|
|
1613
|
+
*/
|
|
1614
|
+
class StructuredObject {
|
|
1615
|
+
/**
|
|
1616
|
+
* Create an object of StructuredObject
|
|
1617
|
+
*
|
|
1618
|
+
* @param apiKey You'll find the API Key on the Twintag project page.
|
|
1619
|
+
*/
|
|
1620
|
+
constructor(apiKey, useCaching = false) {
|
|
1621
|
+
this.name = '';
|
|
1622
|
+
this.apiName = '';
|
|
1623
|
+
this.isList = false;
|
|
1624
|
+
this.isGlobal = false;
|
|
1625
|
+
this._useCaching = false;
|
|
1626
|
+
this.client = new Client(apiKey);
|
|
1627
|
+
this._useCaching = useCaching;
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Get the attributes of the object of the project. Returns the list of attributes.
|
|
1631
|
+
*/
|
|
1632
|
+
getAttributes() {
|
|
1633
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1634
|
+
const url = this.getURL(`/property?object=${this.apiName}&`, this.$schemaScope);
|
|
1635
|
+
const [res, err] = yield this.client.get(url);
|
|
1636
|
+
if (err) {
|
|
1637
|
+
err.setMessage(`failed to get attributes: ${err.message}`);
|
|
1638
|
+
throw err;
|
|
1639
|
+
}
|
|
1640
|
+
return res;
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Get a specific attribute by name
|
|
1645
|
+
*
|
|
1646
|
+
* @param attributeName Name of the attribute
|
|
1647
|
+
*/
|
|
1648
|
+
getAttribute(attributeName) {
|
|
1649
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1650
|
+
const url = this.getURL(`/property?object=${this.apiName}&property=${attributeName}&`, this.$schemaScope);
|
|
1651
|
+
const [res, err] = yield this.client.get(url);
|
|
1652
|
+
if (err) {
|
|
1653
|
+
err.setMessage(`failed to get attribute for ${attributeName}: ${err.message}`);
|
|
1654
|
+
throw err;
|
|
1655
|
+
}
|
|
1656
|
+
return res;
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
/**
|
|
1660
|
+
* Create a new attribute for the object of a project
|
|
1661
|
+
*
|
|
1662
|
+
* @param attributeName Name of the attribute
|
|
1663
|
+
* @param type Type of the attribute. Use the {@link AttributeType | AttributeType} enum or "string" for string type, "number" for number type and "datetime" for a datetime type, "richtext" for rich text type, "file" for file type, "boolean" for boolean type
|
|
1664
|
+
* @param positionBefore The apiName of the property before which the newly created property is placed
|
|
1665
|
+
*/
|
|
1666
|
+
newAttribute(attributeName, type, positionBefore) {
|
|
1667
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1668
|
+
const url = environment.adminHost + '/api/v1/property';
|
|
1669
|
+
const reqProperty = {
|
|
1670
|
+
$object: this.apiName,
|
|
1671
|
+
name: attributeName,
|
|
1672
|
+
type: this.getTypeByName(type),
|
|
1673
|
+
nextProperty: positionBefore,
|
|
1674
|
+
};
|
|
1675
|
+
const [res, err] = yield this.client.put(url, reqProperty);
|
|
1676
|
+
if (err) {
|
|
1677
|
+
err.setMessage(`failed to create new attribute: ${err.message}`);
|
|
1678
|
+
throw err;
|
|
1679
|
+
}
|
|
1680
|
+
return res;
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
/**
|
|
1684
|
+
* Delete a attribute for the object of a project
|
|
1685
|
+
*
|
|
1686
|
+
* @param attributeName Name of the attribute
|
|
1687
|
+
*/
|
|
1688
|
+
deleteAttribute(attributeName) {
|
|
1689
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1690
|
+
const url = environment.adminHost + '/api/v1/property';
|
|
1691
|
+
const reqProperty = {
|
|
1692
|
+
$object: this.apiName,
|
|
1693
|
+
name: attributeName,
|
|
1694
|
+
};
|
|
1695
|
+
const [, err] = yield this.client.delete(url, reqProperty);
|
|
1696
|
+
if (err) {
|
|
1697
|
+
err.setMessage(`failed to delete attribute: ${attributeName}: ${err.message}`);
|
|
1698
|
+
throw err;
|
|
1699
|
+
}
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Update an attribute for an object of a project
|
|
1704
|
+
*
|
|
1705
|
+
* @param property The desired state of the attribute. $qid is required in the object
|
|
1706
|
+
*
|
|
1707
|
+
*/
|
|
1708
|
+
updateAttribute(property) {
|
|
1709
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1710
|
+
const url = environment.adminHost + '/api/v1/property';
|
|
1711
|
+
if (!property.$qid) {
|
|
1712
|
+
throw new Error(`$qid is not provided in the request object`);
|
|
1713
|
+
}
|
|
1714
|
+
const reqProperty = {
|
|
1715
|
+
$object: this.apiName,
|
|
1716
|
+
$qid: property.$qid,
|
|
1717
|
+
name: property.name,
|
|
1718
|
+
nextProperty: property.nextProperty,
|
|
1719
|
+
apiName: property.apiName,
|
|
1720
|
+
};
|
|
1721
|
+
const [res, err] = yield this.client.put(url, reqProperty);
|
|
1722
|
+
if (err) {
|
|
1723
|
+
err.setMessage(`failed to update attribute: ${property.name}: ${err.message}`);
|
|
1724
|
+
throw err;
|
|
1725
|
+
}
|
|
1726
|
+
return res;
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* Rename the object
|
|
1731
|
+
* @param newName
|
|
1732
|
+
*/
|
|
1733
|
+
rename(newName) {
|
|
1734
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1735
|
+
const url = environment.adminHost + '/api/v1/object';
|
|
1736
|
+
const reqobject = {
|
|
1737
|
+
$qid: this.$qid,
|
|
1738
|
+
name: newName,
|
|
1739
|
+
};
|
|
1740
|
+
const [resp, err] = yield this.client.put(url, reqobject);
|
|
1741
|
+
if (err) {
|
|
1742
|
+
err.setMessage(`failed to rename structured object: ${err.message}`);
|
|
1743
|
+
throw err;
|
|
1744
|
+
}
|
|
1745
|
+
return resp;
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
/**
|
|
1749
|
+
* Update the key property of the object.
|
|
1750
|
+
* If a attribute by the given name already exists, the attribute will be marked as key attribute.
|
|
1751
|
+
* If the attribute by the given name doesnot exists, a new attribute will be created and marked as key attribute.
|
|
1752
|
+
* If instances for the object already exist, key property for the object cannot be updated.
|
|
1753
|
+
* @param attributeName
|
|
1754
|
+
*/
|
|
1755
|
+
updateKeyAttribute(attributeName) {
|
|
1756
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1757
|
+
const url = environment.adminHost + '/api/v1/object';
|
|
1758
|
+
const reqobject = {
|
|
1759
|
+
$qid: this.$qid,
|
|
1760
|
+
keyProperty: attributeName,
|
|
1761
|
+
};
|
|
1762
|
+
const [resp, err] = yield this.client.put(url, reqobject);
|
|
1763
|
+
if (err) {
|
|
1764
|
+
err.setMessage(`failed to update key property of object: ${err.message}`);
|
|
1765
|
+
throw err;
|
|
1766
|
+
}
|
|
1767
|
+
return resp;
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
/**
|
|
1771
|
+
* Update the access of the object.
|
|
1772
|
+
*/
|
|
1773
|
+
updateAccess(access) {
|
|
1774
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1775
|
+
const url = environment.adminHost + '/api/v1/object';
|
|
1776
|
+
const reqobject = {
|
|
1777
|
+
$qid: this.$qid,
|
|
1778
|
+
access: access,
|
|
1779
|
+
};
|
|
1780
|
+
const [resp, err] = yield this.client.put(url, reqobject);
|
|
1781
|
+
if (err) {
|
|
1782
|
+
err.setMessage(`failed to update access of object: ${err.message}`);
|
|
1783
|
+
throw err;
|
|
1784
|
+
}
|
|
1785
|
+
return resp;
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Add translation column for an existing structured data object column
|
|
1790
|
+
* @param langAttributes: indexed type. pass key value pair for language and corresponding column name (see example below)
|
|
1791
|
+
* @param parent: api name of column for which translation column is being created
|
|
1792
|
+
* Example
|
|
1793
|
+
* ```js
|
|
1794
|
+
* //first create column for which translation has to be added
|
|
1795
|
+
* const col = await object.newAttribute('col name')
|
|
1796
|
+
*
|
|
1797
|
+
* let langAttr = {
|
|
1798
|
+
* 'fr':'french column name',
|
|
1799
|
+
* 'nl':'dutch column name'
|
|
1800
|
+
* }
|
|
1801
|
+
*
|
|
1802
|
+
* const res = await object.addTranslationAttribute(langAttr, col.apiName)
|
|
1803
|
+
* ```
|
|
1804
|
+
* This will create 2 language columns, each for french and dutch language.
|
|
1805
|
+
* @returns Promise<Attribute[]>
|
|
1806
|
+
*/
|
|
1807
|
+
addTranslationAttribute(langAttributes, parent) {
|
|
1808
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1809
|
+
const resAttributes = [];
|
|
1810
|
+
if (langAttributes == null) {
|
|
1811
|
+
return null;
|
|
1812
|
+
}
|
|
1813
|
+
for (const [language, columnName] of Object.entries(langAttributes)) {
|
|
1814
|
+
const reqBody = {
|
|
1815
|
+
$object: this.apiName,
|
|
1816
|
+
$schemaScope: this.$schemaScope,
|
|
1817
|
+
name: columnName,
|
|
1818
|
+
parent: parent,
|
|
1819
|
+
language: language,
|
|
1820
|
+
type: this.getTypeByName('string'),
|
|
1821
|
+
};
|
|
1822
|
+
const url = environment.adminHost + '/api/v1/property';
|
|
1823
|
+
const [resp, err] = yield this.client.put(url, reqBody);
|
|
1824
|
+
if (err) {
|
|
1825
|
+
err.setMessage(`failed to add translation attribute ${columnName}: ${err.message}`);
|
|
1826
|
+
}
|
|
1827
|
+
if (resp) {
|
|
1828
|
+
resAttributes.push(resp);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
return resAttributes;
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
getTypeByName(type) {
|
|
1835
|
+
switch (type === null || type === void 0 ? void 0 : type.toLowerCase()) {
|
|
1836
|
+
case 'number':
|
|
1837
|
+
return 2;
|
|
1838
|
+
case 'datetime':
|
|
1839
|
+
return 3;
|
|
1840
|
+
case 'richtext':
|
|
1841
|
+
return 4;
|
|
1842
|
+
case 'file':
|
|
1843
|
+
return 5;
|
|
1844
|
+
case 'boolean':
|
|
1845
|
+
return 6;
|
|
1846
|
+
default:
|
|
1847
|
+
return 1;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Get URL
|
|
1852
|
+
* @internal
|
|
1853
|
+
*/
|
|
1854
|
+
getURL(url, schemaScope) {
|
|
1855
|
+
if (this._useCaching) {
|
|
1856
|
+
return environment.cachingHost + url + `schemaScope=${schemaScope}`;
|
|
1857
|
+
}
|
|
1858
|
+
return environment.adminHost + '/api/v1' + url;
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Types of attributes
|
|
1863
|
+
*/
|
|
1864
|
+
var AttributeType;
|
|
1865
|
+
(function (AttributeType) {
|
|
1866
|
+
AttributeType["String"] = "string";
|
|
1867
|
+
AttributeType["Number"] = "number";
|
|
1868
|
+
AttributeType["Datetime"] = "datetime";
|
|
1869
|
+
AttributeType["Richtext"] = "richtext";
|
|
1870
|
+
AttributeType["File"] = "file";
|
|
1871
|
+
AttributeType["Boolean"] = "boolean";
|
|
1872
|
+
})(AttributeType || (AttributeType = {}));
|
|
1873
|
+
|
|
1874
|
+
/**
|
|
1875
|
+
* The twintag class allows you to interact with a view into a twintag.
|
|
1876
|
+
* A view is represented by a `qid`. This is the string you see in its url:
|
|
1877
|
+
* `https://twintag.io/<qid>`.
|
|
1878
|
+
* A twintag can have multiple views, each view can have different rights associated.
|
|
1879
|
+
* For example: owner, download-only, upload-only, ...
|
|
1880
|
+
*
|
|
1881
|
+
* To construct a twintag object, you pass its QID, E.g.:
|
|
1882
|
+
* ```
|
|
1883
|
+
* let twintag = new Zaza.Twintag(viewId)
|
|
1884
|
+
* ```
|
|
1885
|
+
*/
|
|
1886
|
+
class Twintag {
|
|
1887
|
+
/**
|
|
1888
|
+
* Construct a view by its QID.
|
|
1889
|
+
*
|
|
1890
|
+
* @param init Internal parameter.
|
|
1891
|
+
*/
|
|
1892
|
+
constructor(qid) {
|
|
1893
|
+
this._base = new TwintagBase(qid);
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* _setConfig allows us to pass internal state.
|
|
1897
|
+
*
|
|
1898
|
+
* @internal */
|
|
1899
|
+
_setConfig(init) {
|
|
1900
|
+
this._base.setconfig(init);
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Delete a project twintag along with its metadata (if any)
|
|
1904
|
+
* This view instance should be generated with project.
|
|
1905
|
+
*
|
|
1906
|
+
* Example:
|
|
1907
|
+
* ```js
|
|
1908
|
+
* const vi = project.getView('viewid')
|
|
1909
|
+
* await vi.deleteProjectTwintag()
|
|
1910
|
+
* ```
|
|
1911
|
+
*/
|
|
1912
|
+
deleteProjectTwintag() {
|
|
1913
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1914
|
+
if (!this._base._data) {
|
|
1915
|
+
yield this._base.data();
|
|
1916
|
+
}
|
|
1917
|
+
const url = this._base.twintagURL();
|
|
1918
|
+
const [, err] = yield this._base._client.delete(url);
|
|
1919
|
+
if (err) {
|
|
1920
|
+
err.setMessage(`failed to delete project twintag`);
|
|
1921
|
+
throw err;
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
/**
|
|
1928
|
+
* The project class allows you to interact with a Twintag project.
|
|
1929
|
+
*
|
|
1930
|
+
* To construct a project object you pass the API key you find
|
|
1931
|
+
* on the Twintag project page. E.g.:
|
|
1932
|
+
* ```
|
|
1933
|
+
* let project = new Twintag.Project('<Project API key>')
|
|
1934
|
+
* ```
|
|
1935
|
+
*/
|
|
1936
|
+
class Project {
|
|
1937
|
+
/**
|
|
1938
|
+
* Create a project
|
|
1939
|
+
*
|
|
1940
|
+
* @param apiKey You'll find the API Key on the Twintag project page.
|
|
1941
|
+
*/
|
|
1942
|
+
constructor(apiKey) {
|
|
1943
|
+
this.projectId = '';
|
|
1944
|
+
this._useCaching = false;
|
|
1945
|
+
this.apiKey = apiKey;
|
|
1946
|
+
this.client = new Client(apiKey);
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* set caching host
|
|
1950
|
+
* @param val
|
|
1951
|
+
* @hidden
|
|
1952
|
+
*/
|
|
1953
|
+
useCaching(val) {
|
|
1954
|
+
this._useCaching = val;
|
|
1955
|
+
this.getProjectId();
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Create a bag, automatically linked to the project.
|
|
1959
|
+
*/
|
|
1960
|
+
createBag() {
|
|
1961
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1962
|
+
return yield createBagInternal(this.client, this);
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Create a {@link View | view } object with project-level privileges.
|
|
1967
|
+
* Your project API key is automatically used for all changes.
|
|
1968
|
+
*/
|
|
1969
|
+
getView(qid) {
|
|
1970
|
+
const view = new View(qid);
|
|
1971
|
+
// Pass state
|
|
1972
|
+
view._setConfig({ project: this, client: this.client });
|
|
1973
|
+
return view;
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Create a {@link Twintag | twintag } object with project-level privileges.
|
|
1977
|
+
* Your project API key is automatically used for all changes.
|
|
1978
|
+
*/
|
|
1979
|
+
getTwintag(qid) {
|
|
1980
|
+
const twintag = new Twintag(qid);
|
|
1981
|
+
twintag._setConfig({ project: this, client: this.client });
|
|
1982
|
+
return twintag;
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* List the metadata of a all twintags within your project.
|
|
1986
|
+
* @param lang: optional language value. Allowed inputs are "all" or any language defined in project languages. If no value is passed, then project's default language will be used for returning data
|
|
1987
|
+
* @typeParam T The objects in the resulting array will be cast to this type.
|
|
1988
|
+
*/
|
|
1989
|
+
getMetadata(lang) {
|
|
1990
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1991
|
+
const langParam = lang ? `language=${(lang === 'all' ? '*' : lang)}` : '';
|
|
1992
|
+
const url = this.getURL('/data/metadata?withSDFileURL=false', false, langParam);
|
|
1993
|
+
const [res, err] = yield this.client.get(url);
|
|
1994
|
+
if (err) {
|
|
1995
|
+
err.setMessage('failed to get metadata');
|
|
1996
|
+
throw err;
|
|
1997
|
+
}
|
|
1998
|
+
return res;
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* Create an object for the project. Returns a StructuredObject object on which various operations can be performed.
|
|
2003
|
+
*
|
|
2004
|
+
* @param objectName Name with which the object is to be created
|
|
2005
|
+
* @param objectAPIName APIName with which the object is to be created
|
|
2006
|
+
* @param isList Optional paramaeter to specify if the object is of list type. By default false is set as the value for this param.
|
|
2007
|
+
* @param isGlobal Optional parameter to specify if the object is of global type. By default false is set as the value for this param.
|
|
2008
|
+
* @param keyProperty Optional parameter to specify the key property for the object is. By default no key property will be created.
|
|
2009
|
+
*/
|
|
2010
|
+
newObject(objectName, objectAPIName = "", isList, isGlobal, keyProperty, access) {
|
|
2011
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2012
|
+
const url = environment.adminHost + '/api/v1/object';
|
|
2013
|
+
const reqobject = {
|
|
2014
|
+
name: objectName,
|
|
2015
|
+
apiName: objectAPIName,
|
|
2016
|
+
isList: isList ? isList : false,
|
|
2017
|
+
isGlobal: isGlobal ? isGlobal : false,
|
|
2018
|
+
keyProperty: keyProperty ? keyProperty : '',
|
|
2019
|
+
access: access,
|
|
2020
|
+
};
|
|
2021
|
+
const [obj, err] = yield this.client.put(url, reqobject);
|
|
2022
|
+
if (err) {
|
|
2023
|
+
err.setMessage('failed to create object');
|
|
2024
|
+
throw err;
|
|
2025
|
+
}
|
|
2026
|
+
const object = new StructuredObject(this.apiKey, this._useCaching);
|
|
2027
|
+
object.$qid = obj.$qid;
|
|
2028
|
+
object.$schemaScope = obj.$schemaScope;
|
|
2029
|
+
object.isGlobal = obj.isGlobal;
|
|
2030
|
+
object.isList = obj.isList;
|
|
2031
|
+
object.keyProperty = obj.keyProperty;
|
|
2032
|
+
object.name = obj.name;
|
|
2033
|
+
object.apiName = obj.apiName;
|
|
2034
|
+
object.access = obj.access;
|
|
2035
|
+
return object;
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Get an object by name. Returns a StructuredObject object on which various operations can be performed.
|
|
2040
|
+
*
|
|
2041
|
+
* @param objectAPIName APIName of the object
|
|
2042
|
+
*/
|
|
2043
|
+
getObject(objectAPIName) {
|
|
2044
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2045
|
+
const url = this.getURL(`/object?object=${objectAPIName}`, true);
|
|
2046
|
+
const [obj, err] = yield this.client.get(url);
|
|
2047
|
+
if (err) {
|
|
2048
|
+
err.setMessage('failed to get object');
|
|
2049
|
+
throw err;
|
|
2050
|
+
}
|
|
2051
|
+
const object = new StructuredObject(this.apiKey, this._useCaching);
|
|
2052
|
+
object.$qid = obj.$qid;
|
|
2053
|
+
object.$schemaScope = obj.$schemaScope;
|
|
2054
|
+
object.isGlobal = obj.isGlobal;
|
|
2055
|
+
object.isList = obj.isList;
|
|
2056
|
+
object.keyProperty = obj.keyProperty;
|
|
2057
|
+
object.name = obj.name;
|
|
2058
|
+
object.apiName = obj.apiName;
|
|
2059
|
+
return object;
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* Delete an object by its name
|
|
2064
|
+
*
|
|
2065
|
+
* @param objectAPIName Name of the object
|
|
2066
|
+
*/
|
|
2067
|
+
deleteObject(objectAPIName) {
|
|
2068
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2069
|
+
const url = environment.adminHost + '/api/v1/object?object=' + objectAPIName;
|
|
2070
|
+
const reqobject = {
|
|
2071
|
+
apiName: objectAPIName,
|
|
2072
|
+
};
|
|
2073
|
+
const [, err] = yield this.client.delete(url, reqobject);
|
|
2074
|
+
if (err) {
|
|
2075
|
+
err.setMessage('failed to delete object');
|
|
2076
|
+
throw err;
|
|
2077
|
+
}
|
|
2078
|
+
return;
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* Delete project twintag.
|
|
2083
|
+
* @param viewId view id of the twintag to be deleted.
|
|
2084
|
+
*
|
|
2085
|
+
* Example:
|
|
2086
|
+
* ```js
|
|
2087
|
+
* await project.deleteTwintag('viewid')
|
|
2088
|
+
* ```
|
|
2089
|
+
*/
|
|
2090
|
+
deleteTwintag(viewID) {
|
|
2091
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2092
|
+
return yield this.getTwintag(viewID).deleteProjectTwintag();
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
/**
|
|
2096
|
+
* Get an object for the view
|
|
2097
|
+
*
|
|
2098
|
+
* Required rights: owner.
|
|
2099
|
+
*
|
|
2100
|
+
* @param objectAPIName Name of the object
|
|
2101
|
+
*
|
|
2102
|
+
* @category Structured Data
|
|
2103
|
+
*/
|
|
2104
|
+
object(objectAPIName) {
|
|
2105
|
+
return new ListObject(objectAPIName, this.client, '', this.projectId, this._useCaching);
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
2108
|
+
* @internal
|
|
2109
|
+
* Get project id for when caching is enabled
|
|
2110
|
+
*/
|
|
2111
|
+
getProjectId() {
|
|
2112
|
+
this.projectId = '';
|
|
2113
|
+
let claim;
|
|
2114
|
+
//adding checks for various platforms that uses sdk
|
|
2115
|
+
if (typeof atob !== 'undefined') {
|
|
2116
|
+
//from epsilon pluglet
|
|
2117
|
+
claim = JSON.parse(atob(this.apiKey.split('.')[1]));
|
|
2118
|
+
}
|
|
2119
|
+
else if (typeof window !== 'undefined') {
|
|
2120
|
+
//from document (e.g. index.js)
|
|
2121
|
+
claim = JSON.parse(window.atob(this.apiKey.split('.')[1]));
|
|
2122
|
+
// @ts-ignore
|
|
2123
|
+
}
|
|
2124
|
+
else if (typeof Buffer !== 'undefined') {
|
|
2125
|
+
//from any nodejs application
|
|
2126
|
+
// @ts-ignore
|
|
2127
|
+
claim = JSON.parse(Buffer.from(this.apiKey.split('.')[1], 'base64').toString());
|
|
2128
|
+
}
|
|
2129
|
+
if (claim == null)
|
|
2130
|
+
return null;
|
|
2131
|
+
this.projectId = claim.ProjectId;
|
|
2132
|
+
return this.projectId;
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* @internal
|
|
2136
|
+
* @param url
|
|
2137
|
+
*/
|
|
2138
|
+
getURL(url, argumentPreset, langParam = '') {
|
|
2139
|
+
const append = argumentPreset ? `&schemaScope=${this.projectId}` : `?schemaScope=${this.projectId}`;
|
|
2140
|
+
if (this._useCaching) {
|
|
2141
|
+
langParam = langParam ? `&${langParam}` : '';
|
|
2142
|
+
return `${environment.cachingHost}/${url}${append}${langParam}`;
|
|
2143
|
+
}
|
|
2144
|
+
else {
|
|
2145
|
+
langParam = langParam ? `?${langParam}` : '';
|
|
2146
|
+
return `${environment.adminHost}/api/v1/${url}${langParam}`;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
/**
|
|
2150
|
+
* Get bags in a project
|
|
2151
|
+
*/
|
|
2152
|
+
getBags() {
|
|
2153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2154
|
+
const url = environment.adminHost + '/api/v1/twintags';
|
|
2155
|
+
const [res, err] = yield this.client.get(url);
|
|
2156
|
+
if (err) {
|
|
2157
|
+
err.setMessage('failed to get bag details for the project');
|
|
2158
|
+
throw err;
|
|
2159
|
+
}
|
|
2160
|
+
return res;
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
2163
|
+
/**
|
|
2164
|
+
* Sends email
|
|
2165
|
+
*
|
|
2166
|
+
* @param request EmailRequest object
|
|
2167
|
+
*
|
|
2168
|
+
* Example:
|
|
2169
|
+
*
|
|
2170
|
+
* You can call this method by passing {@link EmailRequest}:
|
|
2171
|
+
* ```js
|
|
2172
|
+
* await projectObj.sendToSubscribers({
|
|
2173
|
+
* recepients: ["to@mail.com"]
|
|
2174
|
+
* body: "email body"
|
|
2175
|
+
* subject: "email subject"
|
|
2176
|
+
* cc: ["cc@mail.com"]
|
|
2177
|
+
* bcc: ["bcc@mail.com"]
|
|
2178
|
+
* })
|
|
2179
|
+
* ```
|
|
2180
|
+
* @category Notifications
|
|
2181
|
+
*/
|
|
2182
|
+
sendToSubscribers(request) {
|
|
2183
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2184
|
+
const client = yield this.client;
|
|
2185
|
+
const url = environment.adminHost + '/api/v1/subscribers/send';
|
|
2186
|
+
const [res, err] = yield client.post(url, request, { headers: { 'Content-Type': 'application/json' } });
|
|
2187
|
+
if (err) {
|
|
2188
|
+
err.setMessage('failed to notify to all the subsribers');
|
|
2189
|
+
throw err;
|
|
2190
|
+
}
|
|
2191
|
+
return res;
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Adds languages for a project.
|
|
2196
|
+
* Example:
|
|
2197
|
+
* ```js
|
|
2198
|
+
* await project.setAllowedLanguages(['en','nl'])
|
|
2199
|
+
* ```
|
|
2200
|
+
*
|
|
2201
|
+
* You can set default language for project in same function as well
|
|
2202
|
+
* Example:
|
|
2203
|
+
* ```js
|
|
2204
|
+
* await project.setAllowedLanguages(['en','nl'], 'nl')
|
|
2205
|
+
* ```
|
|
2206
|
+
*
|
|
2207
|
+
* @param request: array of languages
|
|
2208
|
+
* @param defaultLanguage: optional
|
|
2209
|
+
* @category Languages
|
|
2210
|
+
*/
|
|
2211
|
+
setAllowedLanguages(request, defaultLanguage) {
|
|
2212
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2213
|
+
const req = { allowedLanguages: request };
|
|
2214
|
+
const url = environment.adminHost + `/api/v1/project/allowedLanguages`;
|
|
2215
|
+
const [res, err] = yield this.client.put(url, req);
|
|
2216
|
+
if (err) {
|
|
2217
|
+
err.setMessage(`failed to add languages: ${err.message}`);
|
|
2218
|
+
throw err;
|
|
2219
|
+
}
|
|
2220
|
+
if (defaultLanguage) {
|
|
2221
|
+
yield this.setDefaultLanguage(defaultLanguage);
|
|
2222
|
+
}
|
|
2223
|
+
return res;
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
/**
|
|
2227
|
+
* Get all allowed languages for a project.
|
|
2228
|
+
* Example:
|
|
2229
|
+
* ```js
|
|
2230
|
+
* let res = await project.getAllowedLanguages()
|
|
2231
|
+
* ```
|
|
2232
|
+
* @returns Promise<string[]>
|
|
2233
|
+
*/
|
|
2234
|
+
getAllowedLanguages() {
|
|
2235
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2236
|
+
const url = environment.adminHost + `/api/v1/project/allowedLanguages`;
|
|
2237
|
+
const [res, err] = yield this.client.get(url);
|
|
2238
|
+
if (err) {
|
|
2239
|
+
err.setMessage(`failed to get allowed languages: ${err.message}`);
|
|
2240
|
+
throw err;
|
|
2241
|
+
}
|
|
2242
|
+
return res;
|
|
2243
|
+
});
|
|
2244
|
+
}
|
|
2245
|
+
/**
|
|
2246
|
+
* Sets default language for the project.
|
|
2247
|
+
* Example:
|
|
2248
|
+
* ```js
|
|
2249
|
+
* await project.setDefaultLanguage('nl')
|
|
2250
|
+
* ```
|
|
2251
|
+
*
|
|
2252
|
+
* @param request: default language.
|
|
2253
|
+
* @category Languages
|
|
2254
|
+
*/
|
|
2255
|
+
setDefaultLanguage(request) {
|
|
2256
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2257
|
+
const req = { defaultLanguage: request };
|
|
2258
|
+
const url = environment.adminHost + `/api/v1/project/defaultLanguage`;
|
|
2259
|
+
const [res, err] = yield this.client.put(url, req);
|
|
2260
|
+
if (err) {
|
|
2261
|
+
err.setMessage(`failed to set default language: ${err.message}`);
|
|
2262
|
+
throw err;
|
|
2263
|
+
}
|
|
2264
|
+
return res;
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* gets default language for the project.
|
|
2269
|
+
* Example:
|
|
2270
|
+
* ```js
|
|
2271
|
+
* await project.getDefaultLanguage()
|
|
2272
|
+
* ```
|
|
2273
|
+
*
|
|
2274
|
+
* @category Languages
|
|
2275
|
+
*/
|
|
2276
|
+
getDefaultLanguage() {
|
|
2277
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2278
|
+
const url = environment.adminHost + `/api/v1/project/defaultLanguage`;
|
|
2279
|
+
const [res, err] = yield this.client.get(url);
|
|
2280
|
+
if (err) {
|
|
2281
|
+
err.setMessage(`failed to get default language: ${err.message}`);
|
|
2282
|
+
throw err;
|
|
2283
|
+
}
|
|
2284
|
+
return res;
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* BagType: Enum for type of bag.
|
|
2290
|
+
*/
|
|
2291
|
+
var BagType;
|
|
2292
|
+
(function (BagType) {
|
|
2293
|
+
BagType["Download"] = "download";
|
|
2294
|
+
BagType["Upload"] = "upload";
|
|
2295
|
+
BagType["UploadDownload"] = "upload-download";
|
|
2296
|
+
BagType["Owner"] = "owner";
|
|
2297
|
+
})(BagType || (BagType = {}));
|
|
2298
|
+
|
|
2299
|
+
/**
|
|
2300
|
+
* A virtual file is a file that doesn't have static content like a normal file.
|
|
2301
|
+
* Instead, the content of the file is materialized upon request.
|
|
2302
|
+
*
|
|
2303
|
+
* To create a virtual file you first construct one of the VirtualFile sub-classes.
|
|
2304
|
+
* Next, you upload them using {@link View.uploadVirtual}. E.g.:
|
|
2305
|
+
* ```js
|
|
2306
|
+
* let virtual = new Twintag.Link("https://example.com")
|
|
2307
|
+
* await view.uploadVirtual(virtual, "My link")
|
|
2308
|
+
* ```
|
|
2309
|
+
*/
|
|
2310
|
+
class VirtualFile {
|
|
2311
|
+
/**
|
|
2312
|
+
* Construct a virtual file.
|
|
2313
|
+
*
|
|
2314
|
+
* @internal
|
|
2315
|
+
* */
|
|
2316
|
+
constructor(mode) {
|
|
2317
|
+
this.mode = mode;
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
/**
|
|
2321
|
+
* A link is a virtual file that represents a web link.
|
|
2322
|
+
*
|
|
2323
|
+
* First construct the link, next upload it to a bag using {@link View.uploadVirtual}. E.g.:
|
|
2324
|
+
* ```js
|
|
2325
|
+
* let virtual = new Twintag.Link("https://example.com")
|
|
2326
|
+
* await view.uploadVirtual(virtual, "My link")
|
|
2327
|
+
* ```
|
|
2328
|
+
*/
|
|
2329
|
+
class Link extends VirtualFile {
|
|
2330
|
+
/**
|
|
2331
|
+
*
|
|
2332
|
+
* Construct a web link by URL.
|
|
2333
|
+
*
|
|
2334
|
+
* @param target The default target is "_blank ". Other targets may be restricted.
|
|
2335
|
+
*/
|
|
2336
|
+
constructor(url, target) {
|
|
2337
|
+
super(50);
|
|
2338
|
+
this.url = url;
|
|
2339
|
+
this.target = "_blank";
|
|
2340
|
+
if (target) {
|
|
2341
|
+
this.target = target;
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
/**
|
|
2345
|
+
* Get the virtual file definition.
|
|
2346
|
+
*
|
|
2347
|
+
* @internal
|
|
2348
|
+
*/
|
|
2349
|
+
GetDefinition() {
|
|
2350
|
+
const def = {
|
|
2351
|
+
specversion: "1.0",
|
|
2352
|
+
definition: {
|
|
2353
|
+
type: "web-link",
|
|
2354
|
+
data: {
|
|
2355
|
+
url: this.url,
|
|
2356
|
+
target: this.target
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
};
|
|
2360
|
+
return def;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
export { AttributeType, BagType, FileUploader, Link, Project, VERSION, View, createBag, retryRequest, setAdminHost, setCachingHost, setHost };
|
|
2365
|
+
//# sourceMappingURL=twintag.esm.js.map
|