skapi-js 0.2.0 → 0.2.2

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.
@@ -0,0 +1,36 @@
1
+ import { Form, FormSubmitCallback, FetchOptions, Connection } from '../Types';
2
+ export declare function getConnection(): Promise<Connection | null>;
3
+ export declare function listHostDirectory(params: {
4
+ service: string;
5
+ dir: string;
6
+ }, fetchOptions: FetchOptions): Promise<any>;
7
+ export declare function request(url: string, data?: Form<any> | null, options?: {
8
+ fetchOptions?: FetchOptions & FormSubmitCallback;
9
+ auth?: boolean;
10
+ method?: string;
11
+ meta?: Record<string, any>;
12
+ bypassAwaitConnection?: boolean;
13
+ responseType?: string;
14
+ contentType?: string;
15
+ }): Promise<any>;
16
+ export declare function secureRequest<RequestParams = {
17
+ url: string;
18
+ data?: any;
19
+ sync?: boolean;
20
+ }>(params: RequestParams | RequestParams[]): Promise<any>;
21
+ export declare function mock(data: Form<any | {
22
+ raise?: 'ERR_INVALID_REQUEST' | 'ERR_INVALID_PARAMETER' | 'SOMETHING_WENT_WRONG' | 'ERR_EXISTS' | 'ERR_NOT_EXISTS';
23
+ }>, formCallback?: FormSubmitCallback, options?: {
24
+ auth?: boolean;
25
+ method?: string;
26
+ meta?: Record<string, any>;
27
+ bypassAwaitConnection?: boolean;
28
+ responseType?: string;
29
+ contentType?: string;
30
+ }): Promise<{
31
+ mockResponse: Record<string, any>;
32
+ }>;
33
+ export declare function getFormResponse(): Promise<any>;
34
+ export declare function formHandler(options?: {
35
+ preventMultipleCalls: boolean;
36
+ }): (target: object, propertyKey: string, descriptor: any) => void;
@@ -0,0 +1,656 @@
1
+ import SkapiError from '../main/error';
2
+ import { MD5 } from '../utils/utils';
3
+ import validator from '../utils/validator';
4
+ const __pendingRequest = {};
5
+ export function getConnection() {
6
+ return this.__connection;
7
+ }
8
+ export async function listHostDirectory(params, fetchOptions) {
9
+ let is_admin = await this.checkAdmin();
10
+ if (is_admin) {
11
+ if (!params?.dir) {
12
+ params.dir = '/';
13
+ }
14
+ return request.bind(this)('list-host-directory', params, {
15
+ fetchOptions,
16
+ auth: true,
17
+ method: 'post'
18
+ });
19
+ }
20
+ return [];
21
+ }
22
+ export async function request(url, data = null, options) {
23
+ options = options || {};
24
+ let { auth = false, method = 'post', meta = null, bypassAwaitConnection = false, } = options;
25
+ method = method.toLowerCase();
26
+ let __connection = bypassAwaitConnection ? null : (await this.__connection);
27
+ if (!__connection && !bypassAwaitConnection) {
28
+ throw new SkapiError('Invalid connection. The service could have been disabled, or has a restricted CORS.', { code: 'INVALID_REQUEST' });
29
+ }
30
+ let token = auth ? this.session?.idToken?.jwtToken : null;
31
+ if (auth) {
32
+ if (!token) {
33
+ this.logout();
34
+ throw new SkapiError('User login is required.', { code: 'INVALID_REQUEST' });
35
+ }
36
+ else {
37
+ let currTime = Date.now() / 1000;
38
+ if (this.session.idToken.payload.exp < currTime) {
39
+ try {
40
+ await this.authentication().getSession({ refreshToken: true });
41
+ token = this.session?.idToken?.jwtToken;
42
+ }
43
+ catch (err) {
44
+ this.logout();
45
+ throw new SkapiError('User login is required.', { code: 'INVALID_REQUEST' });
46
+ }
47
+ }
48
+ }
49
+ }
50
+ let isExternalUrl = '';
51
+ try {
52
+ isExternalUrl = validator.Url(url);
53
+ }
54
+ catch (err) {
55
+ }
56
+ const getEndpoint = async (dest, auth) => {
57
+ const endpoints = await Promise.all([
58
+ this.admin_endpoint,
59
+ this.record_endpoint
60
+ ]);
61
+ const admin = endpoints[0];
62
+ const record = endpoints[1];
63
+ const get_ep = () => {
64
+ switch (dest) {
65
+ case 'get-newsletters':
66
+ case 'get-public-newsletters':
67
+ case 'delete-newsletter':
68
+ case 'block-account':
69
+ case 'register-service':
70
+ case 'get-users':
71
+ case 'post-userdata':
72
+ case 'remove-account':
73
+ case 'post-secure':
74
+ case 'subscribe-newsletter':
75
+ case 'subscribe-public-newsletter':
76
+ case 'signup':
77
+ case 'confirm-signup':
78
+ case 'recover-account':
79
+ case 'mock':
80
+ case 'get-services':
81
+ case 'service':
82
+ case 'grant-access':
83
+ case 'last-verified-email':
84
+ case 'get-newsletter-subscription':
85
+ case 'request-username-change':
86
+ case 'register-subdomain':
87
+ case 'list-host-directory':
88
+ case 'refresh-cdn':
89
+ case 'request-newsletter-sender':
90
+ case 'set-404':
91
+ return {
92
+ public: admin.admin_public,
93
+ private: admin.admin_private
94
+ };
95
+ case 'post-record':
96
+ case 'get-records':
97
+ case 'subscription':
98
+ case 'get-subscription':
99
+ case 'del-records':
100
+ case 'get-table':
101
+ case 'get-tag':
102
+ case 'get-index':
103
+ case 'storage-info':
104
+ case 'get-signed-url':
105
+ case 'grant-private-access':
106
+ case 'request-private-access-key':
107
+ case 'del-files':
108
+ return {
109
+ private: record.record_private,
110
+ public: record.record_public
111
+ };
112
+ default:
113
+ return null;
114
+ }
115
+ };
116
+ return (get_ep()?.[auth ? 'private' : 'public'] || '') + dest;
117
+ };
118
+ let endpoint = isExternalUrl || (await getEndpoint(url, !!auth));
119
+ let service = this.session?.attributes?.['custom:service'] || __connection?.service || this.service;
120
+ let owner = this.session?.attributes?.['custom:owner'] || __connection?.owner || this.owner;
121
+ if (meta) {
122
+ if (typeof meta === 'object' && !Array.isArray(meta)) {
123
+ meta = JSON.parse(JSON.stringify(meta));
124
+ }
125
+ else {
126
+ throw new SkapiError('Invalid meta data.', { code: 'INVALID_REQUEST' });
127
+ }
128
+ }
129
+ if (Array.isArray(data) || data && typeof data !== 'object') {
130
+ throw new SkapiError('Request data should be a JSON Object | FormData | HTMLFormElement.', { code: 'INVALID_REQUEST' });
131
+ }
132
+ let required = options?.responseType !== 'blob' ? { service, owner } : {};
133
+ let fetchOptions = {};
134
+ let { fetchMore = false, progress } = options?.fetchOptions || {};
135
+ if (options?.fetchOptions && Object.keys(options.fetchOptions).length) {
136
+ let fetOpt = validator.Params({
137
+ limit: options.fetchOptions?.limit || 50,
138
+ startKey: options.fetchOptions?.startKey || null,
139
+ ascending: typeof options.fetchOptions?.ascending === 'boolean' ? options.fetchOptions.ascending : true
140
+ }, {
141
+ limit: ['number', () => 50],
142
+ startKey: null,
143
+ ascending: ['boolean', () => true]
144
+ });
145
+ if (fetOpt.hasOwnProperty('limit') && typeof fetOpt.limit === 'number') {
146
+ if (fetOpt.limit > 1000) {
147
+ throw new SkapiError('Fetch limit should be below 1000.', { code: 'INVALID_REQUEST' });
148
+ }
149
+ Object.assign(fetchOptions, { limit: fetOpt.limit });
150
+ }
151
+ if (fetOpt.hasOwnProperty('startKey') && typeof fetOpt.startKey === 'object' && fetOpt.startKey && Object.keys(fetOpt.startKey)) {
152
+ Object.assign(fetchOptions, { startKey: fetOpt.startKey });
153
+ }
154
+ if (fetOpt.hasOwnProperty('ascending') && typeof fetOpt.ascending === 'boolean') {
155
+ Object.assign(fetchOptions, { ascending: fetOpt.ascending });
156
+ }
157
+ }
158
+ Object.assign(required, fetchOptions);
159
+ let isForm = false;
160
+ if (data instanceof SubmitEvent) {
161
+ data = data?.target;
162
+ }
163
+ if (data instanceof HTMLFormElement) {
164
+ data = new FormData(data);
165
+ }
166
+ if (data instanceof FormData) {
167
+ isForm = true;
168
+ }
169
+ if (meta) {
170
+ meta = Object.assign(required, meta);
171
+ }
172
+ else {
173
+ if (!data) {
174
+ data = required;
175
+ }
176
+ else if (isForm) {
177
+ for (let k in required) {
178
+ if (required[k] !== undefined) {
179
+ data.set(k, new Blob([JSON.stringify(required[k])], {
180
+ type: 'application/json'
181
+ }));
182
+ }
183
+ }
184
+ }
185
+ else {
186
+ data = Object.assign(required, data);
187
+ }
188
+ }
189
+ if (isForm && typeof options?.fetchOptions?.formData === 'function') {
190
+ let cb = options.fetchOptions.formData(data);
191
+ if (cb instanceof Promise) {
192
+ cb = await cb;
193
+ }
194
+ if (cb instanceof FormData) {
195
+ data = cb;
196
+ }
197
+ if (data instanceof FormData) {
198
+ let totalFileSize = 0;
199
+ for (let pair of data.entries()) {
200
+ let v = pair[1];
201
+ if (v instanceof File) {
202
+ totalFileSize += v.size;
203
+ }
204
+ else if (v instanceof FileList) {
205
+ if (v && v.length > 0) {
206
+ for (let idx = 0; idx <= v.length - 1; idx++) {
207
+ totalFileSize += v.item(idx).size;
208
+ }
209
+ }
210
+ }
211
+ }
212
+ if (totalFileSize > 4200000) {
213
+ throw new SkapiError('Files cannot exceed 4MB. Use skapi.uploadFiles(...) instead.', { code: 'INVALID_REQUEST' });
214
+ }
215
+ }
216
+ else {
217
+ throw new SkapiError('Callback for extractFormData() should return FormData', { code: 'INVALID_PARAMETER' });
218
+ }
219
+ }
220
+ let requestKey = load_startKey_keys.bind(this)({
221
+ params: data,
222
+ url: isExternalUrl || url,
223
+ fetchMore: isForm ? false : fetchMore
224
+ });
225
+ if (requestKey && typeof requestKey === 'object') {
226
+ return requestKey;
227
+ }
228
+ if (typeof requestKey === 'string') {
229
+ if (!(__pendingRequest[requestKey] instanceof Promise)) {
230
+ let headers = {
231
+ 'Accept': '*/*'
232
+ };
233
+ if (token) {
234
+ headers.Authorization = token;
235
+ }
236
+ if (meta) {
237
+ headers["Content-Meta"] = window.btoa(encodeURIComponent(typeof meta === 'string' ? meta : JSON.stringify(meta)));
238
+ }
239
+ if (options.hasOwnProperty('contentType')) {
240
+ if (options?.contentType) {
241
+ headers["Content-Type"] = options.contentType;
242
+ }
243
+ }
244
+ else if (!(data instanceof FormData)) {
245
+ headers["Content-Type"] = 'application/json';
246
+ }
247
+ let opt = { headers };
248
+ if (options?.responseType) {
249
+ opt.responseType = options.responseType;
250
+ }
251
+ if (method === 'post') {
252
+ __pendingRequest[requestKey] = _post.bind(this)(endpoint, data, opt, progress);
253
+ }
254
+ else if (method === 'get') {
255
+ __pendingRequest[requestKey] = _get.bind(this)(endpoint, data, opt, progress);
256
+ }
257
+ }
258
+ try {
259
+ let response = await __pendingRequest[requestKey];
260
+ if (isForm) {
261
+ return response;
262
+ }
263
+ else {
264
+ return await update_startKey_keys.bind(this)({
265
+ hashedParam: requestKey,
266
+ url,
267
+ response
268
+ });
269
+ }
270
+ }
271
+ catch (err) {
272
+ throw err;
273
+ }
274
+ finally {
275
+ if (requestKey && __pendingRequest.hasOwnProperty(requestKey)) {
276
+ delete __pendingRequest[requestKey];
277
+ }
278
+ }
279
+ }
280
+ }
281
+ ;
282
+ function load_startKey_keys(option) {
283
+ let { params = {}, url, fetchMore = false } = option || {};
284
+ if (params.hasOwnProperty('startKey') && params.startKey) {
285
+ if (typeof params.startKey !== 'object' && !Object.keys(params.startKey).length &&
286
+ params.startKey !== 'start' && params.startKey !== 'end') {
287
+ throw new SkapiError(`"${params.startKey}" is invalid startKey key.`, { code: 'INVALID_PARAMETER' });
288
+ }
289
+ switch (params.startKey) {
290
+ case 'start':
291
+ fetchMore = false;
292
+ delete params.startKey;
293
+ }
294
+ }
295
+ let hashedParams = (() => {
296
+ if (params && typeof params === 'object' && Object.keys(params).length) {
297
+ function orderObjectKeys(obj) {
298
+ function sortObject(obj) {
299
+ if (typeof obj === 'object' && obj) {
300
+ return Object.keys(obj).sort().reduce((res, key) => (res[key] = obj[key], res), {});
301
+ }
302
+ return obj;
303
+ }
304
+ ;
305
+ let _obj = sortObject(obj);
306
+ if (_obj.hasOwnProperty('limit')) {
307
+ delete _obj.limit;
308
+ }
309
+ for (let k in _obj) {
310
+ if (_obj[k] && typeof _obj[k] === 'object') {
311
+ _obj[k] = sortObject(obj[k]);
312
+ }
313
+ }
314
+ return _obj;
315
+ }
316
+ return MD5.hash(url + '/' + JSON.stringify(orderObjectKeys(params)));
317
+ }
318
+ return MD5.hash(url + '/' + this.service);
319
+ })();
320
+ if (!fetchMore && this.__startKeyHistory?.[url]?.[hashedParams]) {
321
+ if (this.__cached_requests?.[url] && this.__cached_requests?.[url]?.[hashedParams]) {
322
+ delete this.__cached_requests[url][hashedParams];
323
+ }
324
+ if (Array.isArray(this.__startKeyHistory[url][hashedParams]) && this.__startKeyHistory[url][hashedParams].length) {
325
+ for (let p of this.__startKeyHistory[url][hashedParams]) {
326
+ let hashedParams_cached = hashedParams + '/' + MD5.hash(JSON.stringify(p));
327
+ if (this.__cached_requests?.[url] && this.__cached_requests?.[url]?.[hashedParams_cached]) {
328
+ delete this.__cached_requests[url][hashedParams_cached];
329
+ }
330
+ }
331
+ }
332
+ delete this.__startKeyHistory[url][hashedParams];
333
+ return hashedParams;
334
+ }
335
+ if (!Array.isArray(this.__startKeyHistory?.[url]?.[hashedParams])) {
336
+ return hashedParams;
337
+ }
338
+ let list_of_startKeys = this.__startKeyHistory[url][hashedParams];
339
+ let last_startKey_key = list_of_startKeys[list_of_startKeys.length - 1];
340
+ let cache_hashedParams = hashedParams;
341
+ if (last_startKey_key) {
342
+ if (last_startKey_key === 'end') {
343
+ return {
344
+ list: [],
345
+ startKey: 'end',
346
+ endOfList: true,
347
+ startKeyHistory: this.__startKeyHistory[url][hashedParams]
348
+ };
349
+ }
350
+ else {
351
+ cache_hashedParams += MD5.hash(last_startKey_key);
352
+ params.startKey = JSON.parse(last_startKey_key);
353
+ }
354
+ }
355
+ if (this.__cached_requests?.[url]?.[cache_hashedParams]) {
356
+ return this.__cached_requests[url][cache_hashedParams];
357
+ }
358
+ return hashedParams;
359
+ }
360
+ ;
361
+ async function update_startKey_keys(option) {
362
+ let { hashedParam, url, response } = option;
363
+ let fetched = null;
364
+ if (response instanceof Promise) {
365
+ fetched = await response;
366
+ }
367
+ else {
368
+ fetched = response;
369
+ }
370
+ if (!fetched ||
371
+ typeof fetched !== 'object' ||
372
+ !fetched.hasOwnProperty('startKey') ||
373
+ !hashedParam ||
374
+ !url) {
375
+ return fetched;
376
+ }
377
+ if (!this.__startKeyHistory.hasOwnProperty(url)) {
378
+ this.__startKeyHistory[url] = {};
379
+ }
380
+ if (!this.__cached_requests?.[url]) {
381
+ this.__cached_requests[url] = {};
382
+ }
383
+ this.__cached_requests[url][hashedParam] = fetched;
384
+ if (!this.__startKeyHistory[url].hasOwnProperty(hashedParam)) {
385
+ this.__startKeyHistory[url][hashedParam] = [];
386
+ }
387
+ let startKey_string = fetched.startKey === 'end' ? 'end' : JSON.stringify(fetched.startKey);
388
+ if (!this.__startKeyHistory[url][hashedParam].includes(startKey_string)) {
389
+ this.__startKeyHistory[url][hashedParam].push(startKey_string);
390
+ }
391
+ this.__cached_requests[url][hashedParam] = fetched;
392
+ return Object.assign({ startKeyHistory: this.__startKeyHistory[url][hashedParam] }, fetched);
393
+ }
394
+ ;
395
+ async function _fetch(url, opt, progress) {
396
+ let fetchProgress = (url, opts, progress) => {
397
+ return new Promise((res, rej) => {
398
+ let xhr = new XMLHttpRequest();
399
+ xhr.open((opt.method || 'GET').toUpperCase(), url);
400
+ for (var k in opts.headers || {}) {
401
+ xhr.setRequestHeader(k, opts.headers[k]);
402
+ }
403
+ if (opt.responseType) {
404
+ xhr.responseType = opt.responseType;
405
+ }
406
+ xhr.onload = () => {
407
+ if (xhr.status >= 200 && xhr.status < 300) {
408
+ if (opts.responseType == 'json' || opts.responseType == 'blob') {
409
+ res(xhr.response);
410
+ }
411
+ else {
412
+ let result = xhr.responseText;
413
+ try {
414
+ result = JSON.parse(result);
415
+ }
416
+ catch (err) { }
417
+ res(result);
418
+ }
419
+ }
420
+ else {
421
+ let status = xhr.status;
422
+ let errCode = [
423
+ 'INVALID_CORS',
424
+ 'INVALID_REQUEST',
425
+ 'SERVICE_DISABLED',
426
+ 'INVALID_PARAMETER',
427
+ 'ERROR',
428
+ 'EXISTS',
429
+ 'NOT_EXISTS'
430
+ ];
431
+ let result = xhr.responseText;
432
+ try {
433
+ result = JSON.parse(result);
434
+ }
435
+ catch (err) { }
436
+ if (typeof result === 'string') {
437
+ let errMsg = xhr.response.split(':');
438
+ let code = errMsg.splice(0, 1)[0].trim();
439
+ rej(new SkapiError(errMsg.join('').trim(), { code: (errCode.includes(code) ? code : 'ERROR') }));
440
+ }
441
+ else if (typeof result === 'object' && result?.message) {
442
+ let code = (result?.code || (status ? status.toString() : null) || 'ERROR');
443
+ rej(new SkapiError(result?.message, { code: code }));
444
+ }
445
+ }
446
+ };
447
+ xhr.onerror = () => rej('Network error');
448
+ xhr.onabort = () => rej('Aborted');
449
+ xhr.ontimeout = () => rej('Timeout');
450
+ if (typeof progress === 'function') {
451
+ xhr.onprogress = (p) => {
452
+ progress({
453
+ status: 'download',
454
+ progress: p.loaded / p.total * 100,
455
+ loaded: p.loaded,
456
+ total: p.total,
457
+ abort: () => xhr.abort()
458
+ });
459
+ };
460
+ if (xhr.upload) {
461
+ xhr.upload.onprogress = (p) => {
462
+ progress({
463
+ status: 'upload',
464
+ progress: p.loaded / p.total * 100,
465
+ loaded: p.loaded,
466
+ total: p.total,
467
+ abort: () => xhr.abort()
468
+ });
469
+ };
470
+ }
471
+ }
472
+ xhr.send(opts.body);
473
+ });
474
+ };
475
+ let received = await fetchProgress(url, {
476
+ headers: opt?.headers,
477
+ body: opt.body,
478
+ responseType: opt?.responseType
479
+ }, progress);
480
+ if (typeof received === 'object' && opt.method === 'GET' && received.hasOwnProperty('body')) {
481
+ try {
482
+ received = JSON.parse(received.body);
483
+ }
484
+ catch (err) { }
485
+ }
486
+ return received;
487
+ }
488
+ ;
489
+ async function _post(url, params, option, progress) {
490
+ let opt = Object.assign({
491
+ method: 'POST'
492
+ }, option, {
493
+ body: params instanceof FormData ? params : JSON.stringify(params)
494
+ });
495
+ return _fetch.bind(this)(url, opt, progress);
496
+ }
497
+ ;
498
+ async function _get(url, params, option, progress) {
499
+ if (params && typeof params === 'object' && Object.keys(params).length) {
500
+ if (url.substring(url.length - 1) !== '?') {
501
+ url = url + '?';
502
+ }
503
+ let query = Object.keys(params)
504
+ .map(k => {
505
+ let value = params[k];
506
+ if (typeof value !== 'string') {
507
+ value = JSON.stringify(value);
508
+ }
509
+ return encodeURIComponent(k) + '=' + encodeURIComponent(value);
510
+ })
511
+ .join('&');
512
+ url += query;
513
+ }
514
+ let opt = Object.assign({
515
+ method: 'GET'
516
+ }, option);
517
+ return _fetch.bind(this)(url, opt, progress);
518
+ }
519
+ ;
520
+ export async function secureRequest(params) {
521
+ let paramsStruct = {
522
+ url: (v) => {
523
+ return validator.Url(v);
524
+ },
525
+ data: null,
526
+ sync: ['boolean', () => true]
527
+ };
528
+ if (Array.isArray(params)) {
529
+ for (let r of params) {
530
+ r = validator.Params(r, paramsStruct);
531
+ }
532
+ }
533
+ else {
534
+ params = validator.Params(params, paramsStruct);
535
+ }
536
+ return await request.bind(this)('post-secure', params, { auth: true });
537
+ }
538
+ ;
539
+ export async function mock(data, formCallback, options) {
540
+ options = options || {};
541
+ if (formCallback && formCallback?.formData && typeof formCallback.formData === 'function') {
542
+ let fetchOptions = {
543
+ formData: formCallback.formData
544
+ };
545
+ Object.assign(options, fetchOptions);
546
+ }
547
+ return request.bind(this)('mock', data, options);
548
+ }
549
+ ;
550
+ export async function getFormResponse() {
551
+ await this.__connection;
552
+ let responseKey = `${this.service}:${MD5.hash(window.location.href.split('?')[0])}`;
553
+ let stored = window.sessionStorage.getItem(responseKey);
554
+ if (stored !== null) {
555
+ try {
556
+ stored = JSON.parse(stored);
557
+ }
558
+ catch (err) { }
559
+ return stored;
560
+ }
561
+ throw new SkapiError("Form response doesn't exist.", { code: 'NOT_EXISTS' });
562
+ }
563
+ ;
564
+ const pendPromise = {};
565
+ export function formHandler(options) {
566
+ let { preventMultipleCalls = false } = options || {};
567
+ return function (target, propertyKey, descriptor) {
568
+ const fn = descriptor.value;
569
+ descriptor.value = function (...arg) {
570
+ let form = arg[0];
571
+ let option = arg?.[1] || {};
572
+ let routeWithDataKey = true;
573
+ let formEl = null;
574
+ let actionDestination = '';
575
+ if (form instanceof SubmitEvent) {
576
+ form.preventDefault();
577
+ let currentUrl = window.location.href;
578
+ formEl = form.target;
579
+ let href = new URL(formEl.action);
580
+ actionDestination = href.href;
581
+ if (!formEl.action || href.href === currentUrl) {
582
+ routeWithDataKey = false;
583
+ }
584
+ }
585
+ const handleResponse = (response) => {
586
+ if (option?.response) {
587
+ if (typeof option.response === 'function')
588
+ return option.response(response);
589
+ else
590
+ throw new SkapiError('Callback "response" should be type: function.', { code: 'INVALID_PARAMETER' });
591
+ }
592
+ if (formEl) {
593
+ if (routeWithDataKey) {
594
+ window.sessionStorage.setItem(`${this.service}:${MD5.hash(actionDestination)}`, JSON.stringify(response));
595
+ window.location.href = actionDestination;
596
+ }
597
+ }
598
+ return response;
599
+ };
600
+ let response;
601
+ let handleError = (err) => {
602
+ if (form instanceof SubmitEvent) {
603
+ form.preventDefault();
604
+ }
605
+ let is_err = err instanceof Error ? err : new SkapiError(err);
606
+ if (option?.onerror) {
607
+ if (typeof option.onerror === 'function')
608
+ return option.onerror(is_err);
609
+ else
610
+ throw new SkapiError('Callback "onerror" should be type: function.', { code: 'INVALID_PARAMETER' });
611
+ }
612
+ throw is_err;
613
+ };
614
+ const executeMethod = () => {
615
+ try {
616
+ response = fn.bind(this)(...arg);
617
+ }
618
+ catch (err) {
619
+ let is_err = handleError(err);
620
+ if (is_err instanceof Error) {
621
+ throw is_err;
622
+ }
623
+ return is_err;
624
+ }
625
+ if (response instanceof Promise) {
626
+ return (async () => {
627
+ try {
628
+ let resolved = await response;
629
+ return handleResponse(resolved);
630
+ }
631
+ catch (err) {
632
+ return handleError(err);
633
+ }
634
+ })();
635
+ }
636
+ };
637
+ if (preventMultipleCalls) {
638
+ return (async () => {
639
+ if (pendPromise?.[propertyKey] instanceof Promise) {
640
+ let res = await pendPromise[propertyKey];
641
+ pendPromise[propertyKey] = null;
642
+ return res;
643
+ }
644
+ else {
645
+ pendPromise[propertyKey] = executeMethod().finally(() => {
646
+ pendPromise[propertyKey] = null;
647
+ });
648
+ return pendPromise[propertyKey];
649
+ }
650
+ })();
651
+ }
652
+ return executeMethod();
653
+ };
654
+ };
655
+ }
656
+ ;