skapi-js 1.0.0-alpha.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  import { Form, FormSubmitCallback, FetchOptions, Connection } from '../Types';
2
2
  export declare function getConnection(): Promise<Connection>;
3
3
  export declare function request(url: string, data?: Form<any> | null, options?: {
4
+ noParams?: boolean;
4
5
  fetchOptions?: FetchOptions & FormSubmitCallback;
5
6
  auth?: boolean;
6
7
  method?: string;
@@ -1,5 +1,5 @@
1
1
  import SkapiError from '../main/error';
2
- import { MD5 } from '../utils/utils';
2
+ import { MD5, generateRandom } from '../utils/utils';
3
3
  import validator from '../utils/validator';
4
4
  const __pendingRequest = {};
5
5
  export function getConnection() {
@@ -74,6 +74,7 @@ export async function request(url, data = null, options) {
74
74
  case 'refresh-cdn':
75
75
  case 'request-newsletter-sender':
76
76
  case 'set-404':
77
+ case 'subdomain-info':
77
78
  return {
78
79
  public: admin.admin_public,
79
80
  private: admin.admin_private
@@ -119,14 +120,16 @@ export async function request(url, data = null, options) {
119
120
  let fetchOptions = {};
120
121
  let { fetchMore = false, progress } = options?.fetchOptions || {};
121
122
  if (options?.fetchOptions && Object.keys(options.fetchOptions).length) {
122
- let fetOpt = validator.Params({
123
- limit: options.fetchOptions?.limit || 50,
124
- startKey: options.fetchOptions?.startKey || null,
125
- ascending: typeof options.fetchOptions?.ascending === 'boolean' ? options.fetchOptions.ascending : true
126
- }, {
127
- limit: ['number', () => 50],
123
+ let fetOpt = {};
124
+ for (let k of ['limit', 'startKey', 'ascending']) {
125
+ if (options.fetchOptions.hasOwnProperty(k)) {
126
+ fetOpt[k] = options.fetchOptions[k];
127
+ }
128
+ }
129
+ fetOpt = validator.Params(fetOpt, {
130
+ limit: 'number',
128
131
  startKey: null,
129
- ascending: ['boolean', () => true]
132
+ ascending: 'boolean'
130
133
  });
131
134
  if (fetOpt.hasOwnProperty('limit') && typeof fetOpt.limit === 'number') {
132
135
  if (fetOpt.limit > 1000) {
@@ -222,7 +225,16 @@ export async function request(url, data = null, options) {
222
225
  headers.Authorization = token;
223
226
  }
224
227
  if (meta) {
225
- headers["Content-Meta"] = window.btoa(encodeURIComponent(typeof meta === 'string' ? meta : JSON.stringify(meta)));
228
+ let meta_key = '__meta__' + generateRandom(16);
229
+ if (data instanceof FormData) {
230
+ headers["Content-Meta"] = window.btoa(encodeURIComponent(JSON.stringify({
231
+ meta_key: meta_key,
232
+ merge: 'data'
233
+ })));
234
+ data.set(meta_key, new Blob([JSON.stringify(meta)], {
235
+ type: 'application/json'
236
+ }));
237
+ }
226
238
  }
227
239
  if (options.hasOwnProperty('contentType')) {
228
240
  if (options?.contentType) {
@@ -240,7 +252,7 @@ export async function request(url, data = null, options) {
240
252
  __pendingRequest[requestKey] = _post.bind(this)(endpoint, data, opt, progress);
241
253
  }
242
254
  else if (method === 'get') {
243
- __pendingRequest[requestKey] = _get.bind(this)(endpoint, data, opt, progress);
255
+ __pendingRequest[requestKey] = _get.bind(this)(endpoint, data, opt, progress, options?.noParams);
244
256
  }
245
257
  try {
246
258
  let response = await __pendingRequest[requestKey];
@@ -482,8 +494,8 @@ async function _post(url, params, option, progress) {
482
494
  return _fetch.bind(this)(url, opt, progress);
483
495
  }
484
496
  ;
485
- async function _get(url, params, option, progress) {
486
- if (params && typeof params === 'object' && Object.keys(params).length) {
497
+ async function _get(url, params, option, progress, noParams) {
498
+ if (params && typeof params === 'object' && !noParams && Object.keys(params).length) {
487
499
  if (url.substring(url.length - 1) !== '?') {
488
500
  url = url + '?';
489
501
  }
@@ -571,10 +583,12 @@ export function formHandler(options) {
571
583
  }
572
584
  const handleResponse = (response) => {
573
585
  if (option?.response) {
574
- if (typeof option.response === 'function')
586
+ if (typeof option.response === 'function') {
575
587
  return option.response(response);
576
- else
588
+ }
589
+ else {
577
590
  throw new SkapiError('Callback "response" should be type: function.', { code: 'INVALID_PARAMETER' });
591
+ }
578
592
  }
579
593
  if (formEl) {
580
594
  if (routeWithDataKey) {
@@ -589,14 +603,21 @@ export function formHandler(options) {
589
603
  if (form instanceof SubmitEvent) {
590
604
  form.preventDefault();
591
605
  }
592
- let is_err = err instanceof Error ? err : new SkapiError(err);
606
+ if (err instanceof SkapiError) {
607
+ err.name = propertyKey + '()';
608
+ }
609
+ else {
610
+ err = err instanceof Error ? err : new SkapiError(err, { name: propertyKey + '()' });
611
+ }
593
612
  if (option?.onerror) {
594
- if (typeof option.onerror === 'function')
595
- return option.onerror(is_err);
596
- else
597
- throw new SkapiError('Callback "onerror" should be type: function.', { code: 'INVALID_PARAMETER' });
613
+ if (typeof option.onerror === 'function') {
614
+ return option.onerror(err);
615
+ }
616
+ else {
617
+ return new SkapiError('Callback "onerror" should be type: function.', { code: 'INVALID_PARAMETER', name: propertyKey + '()' });
618
+ }
598
619
  }
599
- throw is_err;
620
+ return err;
600
621
  };
601
622
  const executeMethod = () => {
602
623
  try {
@@ -616,7 +637,11 @@ export function formHandler(options) {
616
637
  return handleResponse(resolved);
617
638
  }
618
639
  catch (err) {
619
- return handleError(err);
640
+ let is_err = handleError(err);
641
+ if (is_err instanceof Error) {
642
+ throw is_err;
643
+ }
644
+ return is_err;
620
645
  }
621
646
  })();
622
647
  }
@@ -624,9 +649,7 @@ export function formHandler(options) {
624
649
  if (preventMultipleCalls) {
625
650
  return (async () => {
626
651
  if (pendPromise?.[propertyKey] instanceof Promise) {
627
- let res = await pendPromise[propertyKey];
628
- pendPromise[propertyKey] = null;
629
- return res;
652
+ return pendPromise[propertyKey];
630
653
  }
631
654
  else {
632
655
  pendPromise[propertyKey] = executeMethod().finally(() => {
@@ -2,7 +2,6 @@ import { DatabaseResponse, FetchOptions, Form, Newsletters, SubscriptionGroup }
2
2
  export declare function getSubscriptions(params: {
3
3
  subscriber?: string;
4
4
  subscription?: string;
5
- group?: number;
6
5
  blocked?: boolean;
7
6
  }, fetchOptions?: FetchOptions, _mapper?: Function): Promise<DatabaseResponse<{
8
7
  subscriber: string;
@@ -22,7 +21,7 @@ export declare function getSubscribers(option: SubscriptionGroup<number | undefi
22
21
  blocked?: boolean;
23
22
  }, fetchOptions: FetchOptions): Promise<DatabaseResponse<any>>;
24
23
  export declare function getNewsletterSubscription(params: {
25
- group?: number;
24
+ group?: number | 'public' | 'authorized';
26
25
  }): Promise<{
27
26
  active: boolean;
28
27
  timestamp: number;
@@ -4,19 +4,7 @@ import { request } from './request';
4
4
  function subscriptionGroupCheck(option) {
5
5
  option = validator.Params(option, {
6
6
  user_id: (v) => validator.UserId(v, '"user_id"'),
7
- group: (v) => {
8
- if (v === '*') {
9
- return v;
10
- }
11
- if (typeof v !== 'number') {
12
- throw new SkapiError('"group" should be type: number.', { code: 'INVALID_PARAMETER' });
13
- }
14
- else if (v < 1 && v > 99) {
15
- throw new SkapiError('"group" should be within range 1 ~ 99.', { code: 'INVALID_PARAMETER' });
16
- }
17
- return v;
18
- }
19
- }, ['user_id', 'group']);
7
+ }, ['user_id']);
20
8
  if (this.__user && option.user_id === this.__user.user_id) {
21
9
  throw new SkapiError(`"user_id" cannot be the user's own ID.`, { code: 'INVALID_PARAMETER' });
22
10
  }
@@ -26,13 +14,13 @@ function subscriptionGroupCheck(option) {
26
14
  export async function getSubscriptions(params, fetchOptions, _mapper) {
27
15
  params = validator.Params(params, {
28
16
  subscriber: (v) => validator.UserId(v, 'User ID in "subscriber"'),
29
- group: 'number',
30
17
  subscription: (v) => validator.UserId(v, 'User ID in "subscription"'),
31
18
  blocked: 'boolean'
32
19
  });
33
20
  if (!params.subscriber && !params.subscription) {
34
21
  throw new SkapiError('At least either "subscriber" or "subscription" should have a value.', { code: 'INVALID_PARAMETER' });
35
22
  }
23
+ Object.assign(params, { group: 1 });
36
24
  let response = await request.bind(this)('get-subscription', params, Object.assign({ auth: true }, { fetchOptions }));
37
25
  response.list = response.list.map(_mapper || ((s) => {
38
26
  let subscription = {};
@@ -48,43 +36,39 @@ export async function getSubscriptions(params, fetchOptions, _mapper) {
48
36
  }
49
37
  export async function subscribe(option) {
50
38
  await this.__connection;
51
- let { user_id, group } = subscriptionGroupCheck.bind(this)(option);
52
- if (typeof group !== 'number') {
53
- throw new SkapiError('"group" should be type: number.', { code: 'INVALID_PARAMETER' });
54
- }
39
+ let { user_id } = subscriptionGroupCheck.bind(this)(option);
55
40
  return await request.bind(this)('subscription', {
56
41
  subscribe: user_id,
57
- group
42
+ group: 1
58
43
  }, { auth: true });
59
44
  }
60
45
  export async function unsubscribe(option) {
61
46
  await this.__connection;
62
- let { user_id, group } = subscriptionGroupCheck.bind(this)(option);
47
+ let { user_id } = subscriptionGroupCheck.bind(this)(option);
63
48
  return await request.bind(this)('subscription', {
64
49
  unsubscribe: user_id,
65
- group
50
+ group: 1
66
51
  }, { auth: true });
67
52
  }
68
53
  export async function blockSubscriber(option) {
69
54
  await this.__connection;
70
- let { user_id, group } = subscriptionGroupCheck.bind(this)(option);
71
- return await request.bind(this)('subscription', { block: user_id, group }, { auth: true });
55
+ let { user_id } = subscriptionGroupCheck.bind(this)(option);
56
+ return await request.bind(this)('subscription', { block: user_id, group: 1 }, { auth: true });
72
57
  }
73
58
  export async function unblockSubscriber(option) {
74
59
  await this.__connection;
75
- let { user_id, group } = subscriptionGroupCheck.bind(this)(option);
76
- return await request.bind(this)('subscription', { unblock: user_id, group }, { auth: true });
60
+ let { user_id } = subscriptionGroupCheck.bind(this)(option);
61
+ return await request.bind(this)('subscription', { unblock: user_id, group: 1 }, { auth: true });
77
62
  }
78
63
  export async function getSubscribedTo(option, fetchOptions) {
79
64
  await this.__connection;
80
65
  option = validator.Params(option, {
81
66
  user_id: (v) => validator.UserId(v, '"user_id"'),
82
- group: 'number',
83
67
  blocked: 'boolean'
84
68
  }) || {};
85
69
  return getSubscriptions.bind(this)({
86
70
  subscriber: option.user_id || this.__user?.user_id,
87
- group: option.group,
71
+ group: 1,
88
72
  blocked: option.blocked
89
73
  }, fetchOptions);
90
74
  }
@@ -93,12 +77,11 @@ export async function getSubscribers(option, fetchOptions) {
93
77
  await this.__connection;
94
78
  option = validator.Params(option, {
95
79
  user_id: (v) => validator.UserId(v, '"user_id"'),
96
- group: 'number',
97
80
  blocked: 'boolean'
98
81
  }) || {};
99
82
  let subParams = {
100
83
  subscription: option.user_id || this.__user?.user_id,
101
- group: option.group,
84
+ group: 1,
102
85
  blocked: option.blocked
103
86
  };
104
87
  return getSubscriptions.bind(this)(subParams, fetchOptions);
@@ -114,7 +97,18 @@ export async function getNewsletterSubscription(params) {
114
97
  }
115
98
  return v;
116
99
  },
117
- group: 'number'
100
+ group: v => {
101
+ if (v === 'public') {
102
+ v = 0;
103
+ }
104
+ if (v === 'authorized') {
105
+ v = 1;
106
+ }
107
+ if (typeof v !== 'number') {
108
+ throw new SkapiError('"group" should be type number | "public" | "authorized".', { code: 'INVALID_PARAMETER' });
109
+ }
110
+ return v;
111
+ }
118
112
  });
119
113
  let list = await request.bind(this)('get-newsletter-subscription', params, { auth: true });
120
114
  let result = [];
@@ -1,5 +1,5 @@
1
1
  import { CognitoUser, CognitoUserSession, CognitoUserPool } from 'amazon-cognito-identity-js';
2
- import { User, Form, FormSubmitCallback, UserProfile, FetchOptions, DatabaseResponse, QueryParams, UserAttributes, PublicUser } from '../Types';
2
+ import { Form, FormSubmitCallback, UserProfile, FetchOptions, DatabaseResponse, UserAttributes, PublicUser } from '../Types';
3
3
  export declare let userPool: CognitoUserPool | null;
4
4
  export declare function setUserPool(params: {
5
5
  UserPoolId: string;
@@ -9,7 +9,7 @@ export declare function authentication(): {
9
9
  getSession: (option?: {
10
10
  refreshToken?: boolean;
11
11
  }) => Promise<CognitoUserSession>;
12
- authenticateUser: (email: string, password: string) => Promise<User>;
12
+ authenticateUser: (email: string, password: string) => Promise<UserProfile>;
13
13
  createCognitoUser: (email: string) => Promise<{
14
14
  cognitoUser: CognitoUser;
15
15
  cognitoUsername: string;
@@ -18,16 +18,16 @@ export declare function authentication(): {
18
18
  };
19
19
  export declare function getProfile(options?: {
20
20
  refreshToken: boolean;
21
- }): Promise<User | null>;
21
+ }): Promise<UserProfile | null>;
22
22
  export declare function checkAdmin(): Promise<boolean>;
23
23
  export declare function logout(): Promise<'SUCCESS: The user has been logged out.'>;
24
24
  export declare function resendSignupConfirmation(redirect: string): Promise<'SUCCESS: Signup confirmation E-Mail has been sent.'>;
25
25
  export declare function recoverAccount(redirect?: boolean | string): Promise<"SUCCESS: Recovery e-mail has been sent.">;
26
26
  export declare function login(form: Form<{
27
- username: string;
27
+ username?: string;
28
28
  email: string;
29
29
  password: string;
30
- }>): Promise<User>;
30
+ }>): Promise<UserProfile>;
31
31
  export declare function signup(form: Form<UserAttributes & {
32
32
  email: String;
33
33
  password: String;
@@ -35,7 +35,7 @@ export declare function signup(form: Form<UserAttributes & {
35
35
  signup_confirmation?: boolean | string;
36
36
  email_subscription?: boolean;
37
37
  login?: boolean;
38
- } & FormSubmitCallback): Promise<User | "SUCCESS: The account has been created. User's signup confirmation is required." | 'SUCCESS: The account has been created.'>;
38
+ } & FormSubmitCallback): Promise<UserProfile | "SUCCESS: The account has been created. User's signup confirmation is required." | 'SUCCESS: The account has been created.'>;
39
39
  export declare function disableAccount(): Promise<'SUCCESS: account has been disabled.'>;
40
40
  export declare function resetPassword(form: Form<{
41
41
  email: string;
@@ -55,8 +55,13 @@ export declare function changePassword(params: {
55
55
  new_password: string;
56
56
  current_password: string;
57
57
  }): Promise<'SUCCESS: Password has been changed.'>;
58
- export declare function updateProfile(form: Form<UserAttributes>): Promise<User>;
59
- export declare function getUsers(params?: QueryParams | null, fetchOptions?: FetchOptions): Promise<DatabaseResponse<PublicUser>>;
58
+ export declare function updateProfile(form: Form<UserAttributes>): Promise<UserProfile>;
59
+ export declare function getUsers(params?: {
60
+ searchFor: string;
61
+ value: string | number | boolean;
62
+ condition?: '>' | '>=' | '=' | '<' | '<=' | '!=' | 'gt' | 'gte' | 'eq' | 'lt' | 'lte' | 'ne';
63
+ range?: string | number | boolean;
64
+ }, fetchOptions?: FetchOptions): Promise<DatabaseResponse<PublicUser>>;
60
65
  export declare function lastVerifiedEmail(params?: {
61
66
  revert: boolean;
62
67
  }): Promise<string | UserProfile>;
@@ -125,7 +125,7 @@ export function authentication() {
125
125
  }
126
126
  });
127
127
  };
128
- const getSession = (option) => {
128
+ const getSession = async (option) => {
129
129
  let { refreshToken = false } = option || {};
130
130
  return new Promise((res, rej) => {
131
131
  cognitoUser = userPool?.getCurrentUser() || null;
@@ -206,18 +206,18 @@ export function authentication() {
206
206
  this.__request_signup_confirmation = null;
207
207
  this.__disabledAccount = null;
208
208
  createCognitoUser(email).then(initUser => {
209
- cognitoUser = initUser.cognitoUser;
210
209
  let username = initUser.cognitoUsername;
211
210
  let authenticationDetails = new AuthenticationDetails({
212
211
  Username: username,
213
212
  Password: password
214
213
  });
215
- cognitoUser.authenticateUser(authenticationDetails, {
214
+ initUser.cognitoUser.authenticateUser(authenticationDetails, {
216
215
  newPasswordRequired: (userAttributes, requiredAttributes) => {
217
216
  this.__request_signup_confirmation = username;
218
217
  if (userAttributes['custom:signup_ticket'] === 'PASS' || userAttributes['custom:signup_ticket'] === 'MEMBER') {
219
- cognitoUser.completeNewPasswordChallenge(password, {}, {
220
- onSuccess: (result) => {
218
+ initUser.cognitoUser.completeNewPasswordChallenge(password, {}, {
219
+ onSuccess: _ => {
220
+ cognitoUser = initUser.cognitoUser;
221
221
  getSession().then(session => res(this.user));
222
222
  },
223
223
  onFailure: (err) => {
@@ -229,7 +229,9 @@ export function authentication() {
229
229
  rej(new SkapiError("User's signup confirmation is required.", { code: 'SIGNUP_CONFIRMATION_NEEDED' }));
230
230
  }
231
231
  },
232
- onSuccess: (logged) => getSession().then(session => res(this.user)),
232
+ onSuccess: _ => getSession().then(_ => {
233
+ res(this.user);
234
+ }),
233
235
  onFailure: (err) => {
234
236
  let error = [err.message || 'Failed to authenticate user.', err?.code || 'INVALID_REQUEST'];
235
237
  if (err.code === "NotAuthorizedException") {
@@ -241,6 +243,12 @@ export function authentication() {
241
243
  error = ['Incorrect username or password.', 'INCORRECT_USERNAME_OR_PASSWORD'];
242
244
  }
243
245
  }
246
+ else if (err.code === "UserNotFoundException") {
247
+ error = ['Incorrect username or password.', 'INCORRECT_USERNAME_OR_PASSWORD'];
248
+ }
249
+ else if (err.code === "TooManyRequestsException" || err.code === "LimitExceededException") {
250
+ error = ['Too many attempts. Please try again later.', 'REQUEST_EXCEED'];
251
+ }
244
252
  let errCode = error[1];
245
253
  let errMsg = error[0];
246
254
  let customErr = error[0].split('#');
@@ -263,7 +271,7 @@ export function authentication() {
263
271
  };
264
272
  }
265
273
  export async function getProfile(options) {
266
- await this.__connection;
274
+ await this.__authConnection;
267
275
  try {
268
276
  await authentication.bind(this)().getSession(options);
269
277
  return this.user;
@@ -316,7 +324,7 @@ export async function resendSignupConfirmation(redirect) {
316
324
  }
317
325
  export async function recoverAccount(redirect = false) {
318
326
  if (typeof redirect === 'string') {
319
- validator.Url(redirect);
327
+ redirect = validator.Url(redirect);
320
328
  }
321
329
  else if (typeof redirect !== 'boolean') {
322
330
  throw new SkapiError('Argument should be type: <boolean | string>.', { code: 'INVALID_REQUEST' });
@@ -329,7 +337,7 @@ export async function recoverAccount(redirect = false) {
329
337
  return 'SUCCESS: Recovery e-mail has been sent.';
330
338
  }
331
339
  export async function login(form) {
332
- await logout.bind(this)();
340
+ await this.logout();
333
341
  let params = validator.Params(form, {
334
342
  username: 'string',
335
343
  email: (v) => validator.Email(v),
@@ -407,18 +415,23 @@ export async function signup(form, option) {
407
415
  }
408
416
  params.signup_confirmation = signup_confirmation;
409
417
  params.email_subscription = option?.email_subscription || false;
410
- delete params.service;
411
- delete params.owner;
412
- await request.bind(this)("signup", params);
418
+ if (!admin_creating_account) {
419
+ delete params.service;
420
+ delete params.owner;
421
+ }
422
+ let resp = await request.bind(this)("signup", params, { auth: admin_creating_account });
413
423
  if (signup_confirmation) {
414
424
  let u = await authentication.bind(this)().createCognitoUser(params.username || params.email);
415
425
  cognitoUser = u.cognitoUser;
416
426
  this.__request_signup_confirmation = u.cognitoUsername;
417
427
  return "SUCCESS: The account has been created. User's signup confirmation is required.";
418
428
  }
419
- if (logUser) {
429
+ if (logUser && !admin_creating_account) {
420
430
  return login.bind(this)({ email: params.username || params.email, password: params.password });
421
431
  }
432
+ if (admin_creating_account) {
433
+ return resp;
434
+ }
422
435
  return 'SUCCESS: The account has been created.';
423
436
  }
424
437
  export async function disableAccount() {
@@ -551,6 +564,9 @@ export async function changePassword(params) {
551
564
  else if (err?.code === "NotAuthorizedException") {
552
565
  rej(new SkapiError('Incorrect password.', { code: 'INVALID_REQUEST' }));
553
566
  }
567
+ else if (err?.code === "TooManyRequestsException" || err?.code === "LimitExceededException") {
568
+ rej(new SkapiError('Too many attempts. Please try again later.', { code: 'REQUEST_EXCEED' }));
569
+ }
554
570
  else {
555
571
  rej(new SkapiError(err?.message || 'Failed to change user password.', { code: err?.code || err?.name }));
556
572
  }
@@ -673,18 +689,18 @@ export async function getUsers(params, fetchOptions) {
673
689
  }
674
690
  const searchForTypes = {
675
691
  'user_id': (v) => validator.UserId(v),
676
- 'name': 'string',
677
692
  'email': (v) => validator.Email(v),
678
693
  'phone_number': (v) => validator.PhoneNumber(v),
679
- 'address': 'string',
680
- 'gender': 'string',
681
- 'birthdate': (v) => validator.Birthdate(v),
682
694
  'locale': (v) => {
683
695
  if (typeof v !== 'string' || typeof v === 'string' && v.length > 5) {
684
696
  throw new SkapiError('Value of "locale" should be a country code.', { code: 'INVALID_PARAMETER' });
685
697
  }
686
698
  return v;
687
699
  },
700
+ 'name': 'string',
701
+ 'address': 'string',
702
+ 'gender': 'string',
703
+ 'birthdate': (v) => validator.Birthdate(v),
688
704
  'timestamp': 'number',
689
705
  'access_group': 'number',
690
706
  'approved': (v) => {
@@ -716,7 +732,9 @@ export async function getUsers(params, fetchOptions) {
716
732
  value: (v) => {
717
733
  let checker = searchForTypes[params.searchFor];
718
734
  if (typeof checker === 'function') {
719
- return checker(v);
735
+ if (!params?.condition || params?.condition === '=' || params?.range) {
736
+ return checker(v);
737
+ }
720
738
  }
721
739
  else if (typeof v !== checker) {
722
740
  throw new SkapiError(`Value does not match the type of "${params.searchFor}" index.`, { code: 'INVALID_PARAMETER' });
@@ -16,5 +16,6 @@ declare function generateRandom(length?: number): string;
16
16
  declare function extractFormMeta(form: Form<any>): {
17
17
  meta: {};
18
18
  files: any[];
19
+ to_bin: any[];
19
20
  };
20
21
  export { extractFormMeta, MD5, generateRandom };
package/js/utils/utils.js CHANGED
@@ -1,4 +1,3 @@
1
- import SkapiError from "../main/error";
2
1
  class MD5 {
3
2
  static hash(str) {
4
3
  if (typeof str !== 'string') {
@@ -182,6 +181,7 @@ function extractFormMeta(form) {
182
181
  meta[key] = val;
183
182
  }
184
183
  }
184
+ let to_bin = [];
185
185
  if (form instanceof FormData) {
186
186
  let meta = {};
187
187
  let totalFileSize = 0;
@@ -190,18 +190,22 @@ function extractFormMeta(form) {
190
190
  let name = pair[0];
191
191
  let v = pair[1];
192
192
  if (v instanceof File) {
193
- if (!files.includes(name)) {
194
- files.push(name);
193
+ if ((totalFileSize + v.size) > 4000000) {
194
+ to_bin.push({ name, file: v });
195
+ continue;
195
196
  }
196
197
  totalFileSize += v.size;
198
+ files.push({ name, file: v });
197
199
  }
198
200
  else if (v instanceof FileList) {
199
- if (!files.includes(name)) {
200
- files.push(name);
201
- }
202
201
  if (v && v.length > 0) {
203
202
  for (let idx = 0; idx <= v.length - 1; idx++) {
203
+ if ((totalFileSize + v.item(idx).size) > 4000000) {
204
+ to_bin.push({ name, file: v.item(idx) });
205
+ continue;
206
+ }
204
207
  totalFileSize += v.item(idx).size;
208
+ files.push({ name, file: v.item(idx) });
205
209
  }
206
210
  }
207
211
  }
@@ -209,10 +213,7 @@ function extractFormMeta(form) {
209
213
  appendData(meta, name, v);
210
214
  }
211
215
  }
212
- if (totalFileSize > 4400000) {
213
- throw new SkapiError('Total File size cannot exceed 4MB. Use skapi.uploadFiles() instead.', { code: 'INVALID_REQUEST' });
214
- }
215
- return { meta, files };
216
+ return { meta, files, to_bin };
216
217
  }
217
218
  if (form instanceof SubmitEvent) {
218
219
  form = form.target;
@@ -262,12 +263,14 @@ function extractFormMeta(form) {
262
263
  }
263
264
  }
264
265
  else if (i.type === 'file') {
265
- if (!files.includes(i.name)) {
266
- files.push(i.name);
267
- }
268
266
  if (i.files && i.files.length > 0) {
269
267
  for (let idx = 0; idx <= i.files.length - 1; idx++) {
268
+ if ((totalFileSize + i.files.item(idx).size) > 4000000) {
269
+ to_bin.push({ name: i.name, file: i.files.item(idx) });
270
+ continue;
271
+ }
270
272
  totalFileSize += i.files.item(idx).size;
273
+ files.push({ name: i.name, file: i.files.item(idx) });
271
274
  }
272
275
  }
273
276
  }
@@ -276,10 +279,7 @@ function extractFormMeta(form) {
276
279
  }
277
280
  }
278
281
  }
279
- if (totalFileSize > 4400000) {
280
- throw new SkapiError('Total File size cannot exceed 4MB. Use skapi.uploadFiles() instead.', { code: 'INVALID_REQUEST' });
281
- }
282
- return { meta, files };
282
+ return { meta, files, to_bin };
283
283
  }
284
284
  return null;
285
285
  }
@@ -85,26 +85,32 @@ function Url(url) {
85
85
  }
86
86
  else {
87
87
  let cu = c.trim();
88
- if (!cu.includes(' ') && !cu.includes(',')) {
89
- if (cu.slice(0, 1) === '/' && baseUrl) {
90
- cu = baseUrl + cu;
88
+ if (cu[0] === '/' && baseUrl) {
89
+ if (baseUrl.slice(0, 5) === 'file:') {
90
+ throw new SkapiError(`"${c}" is an invalid url. Relative URL does not work on local file system. Use full URL string.`, { code: 'INVALID_PARAMETER' });
91
91
  }
92
- else if (cu.slice(0, 1) === '.' && baseUrl) {
93
- cu = window.location.href.split('/').slice(0, -1).join('/') + cu;
94
- }
95
- let _url;
96
- try {
97
- _url = new URL(cu);
98
- }
99
- catch (err) {
100
- throw new SkapiError(`"${c}" is an invalid url.`, { code: 'INVALID_PARAMETER' });
92
+ cu = baseUrl + cu;
93
+ }
94
+ else if (cu[0] === '.' && baseUrl) {
95
+ if (baseUrl.slice(0, 5) === 'file:') {
96
+ throw new SkapiError(`"${c}" is an invalid url. Relative URL does not work on local file system. Use full URL string.`, { code: 'INVALID_PARAMETER' });
101
97
  }
102
- if (_url.protocol) {
103
- let url = _url.href;
104
- if (url.charAt(url.length - 1) === '/')
105
- url = url.substring(0, url.length - 1);
106
- return url;
98
+ let curr_loc = window.location.href.split('?')[0];
99
+ if (curr_loc.slice(-1) !== '/') {
100
+ curr_loc += '/';
107
101
  }
102
+ cu = curr_loc + cu.slice(1);
103
+ }
104
+ let _url;
105
+ try {
106
+ _url = new URL(cu);
107
+ }
108
+ catch (err) {
109
+ throw new SkapiError(`"${c}" is an invalid url.`, { code: 'INVALID_PARAMETER' });
110
+ }
111
+ if (_url.protocol) {
112
+ let url = _url.href;
113
+ return url;
108
114
  }
109
115
  }
110
116
  }
@@ -122,13 +128,13 @@ function specialChars(string, p = 'parameter', allowPeriods = false, allowWhiteS
122
128
  if (typeof s !== 'string') {
123
129
  throw new SkapiError(`${p} should be type: <string | string[]>.`, { code: 'INVALID_PARAMETER' });
124
130
  }
125
- if (!allowWhiteSpace && string.includes(' ')) {
131
+ if (!allowWhiteSpace && s.includes(' ')) {
126
132
  throw new SkapiError(`${p} should not have whitespace.`, { code: 'INVALID_PARAMETER' });
127
133
  }
128
- if (!allowPeriods && string.includes('.')) {
134
+ if (!allowPeriods && s.includes('.')) {
129
135
  throw new SkapiError(`${p} should not have periods.`, { code: 'INVALID_PARAMETER' });
130
136
  }
131
- if (/[`!@#$%^&*()_+\-=\[\]{};':"\\|,<>\/?~]/.test(s)) {
137
+ if (/[!@#$%&*()+\-={};':"\|,<>\/?~]/.test(s)) {
132
138
  throw new SkapiError(`${p} should not have special characters.`, { code: 'INVALID_PARAMETER' });
133
139
  }
134
140
  };