skapi-js 0.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.
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "skapi-js",
3
+ "version": "0.0.1",
4
+ "description": "skapi javascript library",
5
+ "main": "./dist/skapi.js",
6
+ "scripts": {
7
+ "build": "npx tsc ; npx webpack --config webpack.config.js ; npx typedoc"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/broadwayinc/skapi-js.git"
12
+ },
13
+ "author": "Baksa Gimm",
14
+ "copyright.owner": "broadway Inc.",
15
+ "license": "Apache-2.0",
16
+ "bugs": {
17
+ "url": "https://github.com/broadwayinc/skapi-js/issues"
18
+ },
19
+ "homepage": "https://skapi.com",
20
+ "devDependencies": {
21
+ "typedoc": "^0.23.18",
22
+ "typescript": "^4.8.4",
23
+ "webpack": "^5.74.0",
24
+ "webpack-cli": "^4.10.0"
25
+ },
26
+ "keywords": [
27
+ "backend",
28
+ "serverless",
29
+ "skapi",
30
+ "api"
31
+ ],
32
+ "dependencies": {
33
+ "amazon-cognito-identity-js": "^5.2.12"
34
+ }
35
+ }
package/src/Api.ts ADDED
@@ -0,0 +1,3 @@
1
+ import Skapi from "./skapi";
2
+ import SkapiError from "./skapi_error";
3
+ export { Skapi, SkapiError };
package/src/Types.ts ADDED
@@ -0,0 +1,385 @@
1
+ /**
2
+ * Additional option for form requests.
3
+ * You can attach callbacks on response and error.
4
+ * If there is a response callback, form will not trigger redirect.
5
+ * <b>Example:</b>
6
+ *
7
+ * ```
8
+ * <form onsubmit="skapi.method(this, { response:r=>r, onerror: err=>err } ); return false;">
9
+ * <input name='NameIsKey' value='Some value'></input>
10
+ * </form>
11
+ * ```
12
+ */
13
+ export type FormCallbacks = {
14
+ /** Callback for response */
15
+ response?(response: any): any;
16
+ /** Callback on error. When boolen true is given, alertbox will show. */
17
+ onerror?: (error: Error) => any;
18
+ /** Middleware callback for extracted FormData from HTMLFormElement. Will not execute if form is not HTMLFormElement.*/
19
+ formData?: (formData: FormData) => Promise<FormData> | FormData;
20
+ };
21
+
22
+ /**
23
+ * You can pass parameters with html forms if the method supports it.
24
+ *
25
+ * <b>Example:</b>
26
+ *
27
+ * ```
28
+ * <form onsubmit="skapi.method(this, options); return false;">
29
+ * <input name='NameIsKey' value='Some value'></input>
30
+ * </form>
31
+ *
32
+ * // Above is equivalent as skapi.method({NameIsKey: 'Some Value'}, option);
33
+ * // Form is useful when posting binary files.
34
+ * // Javascript FormData is also supported.
35
+ * ```
36
+ */
37
+ export type Form = HTMLFormElement | FormData | Record<string, any>;
38
+
39
+ export type Newsletters = {
40
+ /** Newsletter id */
41
+ message_id: string;
42
+ /** Time sent out */
43
+ timestamp: number;
44
+ /** Number of complaints */
45
+ complaint: number;
46
+ /** Number of read */
47
+ read: number;
48
+ /** Subject */
49
+ subject: string;
50
+ /**
51
+ * Number of bounced.<br>
52
+ * When e-mail address is bounced, skapi no longer sends e-mail to the bounced address.
53
+ */
54
+ bounced: string;
55
+ /**
56
+ * Url of the message html.
57
+ */
58
+ url: string;
59
+ };
60
+
61
+ export type UserProfile = {
62
+ /**
63
+ * User's E-Mail for signin.<br>
64
+ * 64 character max.<br>
65
+ * When E-Mail is changed, E-Mail verified state will be changed to false.<br>
66
+ * E-Mail is only visible to others when set to public.<br>
67
+ * E-Mail should be verified to set to public.
68
+ * */
69
+ email?: string;
70
+ /** User's name */
71
+ name?: string;
72
+ /** User's address */
73
+ address?: string;
74
+ /**
75
+ * User's gender. Can be "female" and "male".<br>
76
+ * Other values may be used when neither of the defined values are applicable.
77
+ */
78
+ gender?: string;
79
+ /** User's birthdate. String format: "1969-07-16" */
80
+ birthdate?: string;
81
+ /**
82
+ * User's phone number. Format: "+0012341234"<br>
83
+ * When phone number is changed, phone number verified state will be changed to false.<br>
84
+ * Phone number is only visible to others when set to public.<br>
85
+ * Phone number should be verified to set to public.
86
+ */
87
+ phone_number?: string;
88
+ /** Subscribes to service newsletters. E-Mail should be verified. */
89
+ email_subscription?: boolean;
90
+ /** When true, Set's E-Mail to public. E-Mail should be verified. */
91
+ email_public?: boolean;
92
+ /** When true, Set's phone number to public. Phone number should be verified. */
93
+ phone_number_public?: boolean;
94
+ /** When true, Set's address to public. */
95
+ address_public?: boolean;
96
+ /** When true, Set's gender to public. */
97
+ gender_public?: boolean;
98
+ /** When true, Set's birthdate to public. */
99
+ birthdate_public?: boolean;
100
+ };
101
+
102
+ export interface User extends UserProfile {
103
+ /** Service id of the user account. */
104
+ service: string;
105
+ /** User id of the service owner. */
106
+ service_owner?: string;
107
+ /** Shows true when user has verified their E-Mail. */
108
+ email_verified?: boolean;
109
+ /** User group that user account is in. */
110
+ group?: number;
111
+ /** Country code of where user signed up from. */
112
+ locale: string;
113
+ /** Last login time */
114
+ log: number;
115
+ /** Shows true when user has verified their phone number. */
116
+ phone_number_verified?: boolean;
117
+ /** User data that has been set to private. The data is only shown to the owner of the account. */
118
+ private_data?: Record<string, any>;
119
+ /** Shows 'PASS' if the account signup was successful. */
120
+ signup_ticket?: string;
121
+ /** User id. */
122
+ sub: string;
123
+ /** Number of the users subscribers. */
124
+ subscribers: number;
125
+ /** Timestamp of user signup time. */
126
+ timestamp: number;
127
+ /** User data. */
128
+ user_data?: Record<string, any>;
129
+ /** User id. Same as 'sub'. */
130
+ user_id: string;
131
+ /** Reference of how others would see the data. Appears only on the owner of the account. */
132
+ what_public_see?: Record<string, any>;
133
+ /** Service that account owns. Appears only on admin users. */
134
+ services?: Array<Service>;
135
+ /** Service access group number. */
136
+ access_group?: number;
137
+ }
138
+
139
+ export type GetRecordParams = {
140
+ /** @ignore */
141
+ service?: string;
142
+ /** Table name */
143
+ table: string;
144
+ /**
145
+ * Query for records that are accessable in certain user groups.
146
+ * User cannot request access that are higher than the accounts user group.
147
+ * Queries private records if 'private' is given.
148
+ * User can only query their own private records or can have access to other private record if access is given.
149
+ */
150
+ access_group?: number | 'private';
151
+ subscription?: {
152
+ /**
153
+ * You can fetch records in certain users subscription records.<br>
154
+ * User will not be able to access the subscription record if the user is not subscribed to the user.
155
+ */
156
+ user_id: string;
157
+ /**
158
+ * Target subscription group number.<br>
159
+ * User will not be able to access subscription group if the user is not subscribed to the group.<br>
160
+ */
161
+ group: number;
162
+ },
163
+ index: {
164
+ /**
165
+ * Index name. Queries list of nested index key if index name ends with period.<br>
166
+ * As example below, you can query all movies under the index name director.spielberg...<br>
167
+ * ex) director.spielberg.<br>
168
+ * Reserved index names are: '$record_id' | '$updated' | '$uploaded' | '$referenced_count'
169
+ * */
170
+ name: string | '$record_id' | '$updated' | '$uploaded' | '$referenced_count';
171
+ /**
172
+ * Index value to search based on the index name.<br>
173
+ * If the index name is a index key name search value type must be string.<br>
174
+ * For reserved index names '$record_id' is an record id string, otherwise is type number.
175
+ */
176
+ value: string | number | boolean;
177
+ /** Search condition. Defaults to '='.*/
178
+ condition?: '>' | '>=' | '=' | '<' | '<=' | '!=' | 'gt' | 'gte' | 'eq' | 'lt' | 'lte' | 'ne';
179
+ /**
180
+ * Range of search. <br>
181
+ * Range does not work with conditions.
182
+ */
183
+ range?: string | number | boolean;
184
+ };
185
+ /**
186
+ * Tags can be queried up to 10 tags at once.
187
+ */
188
+ tags?: string | string[];
189
+ /**
190
+ * Queries records that are referencing other record ids.<br>
191
+ * If user id is given, you can get all records uploaded by certain user.
192
+ */
193
+ reference?: string;
194
+ };
195
+
196
+ export type PostRecordParams = {
197
+ /** Record id to be updated. If omited, New record is uploaded. */
198
+ record_id?: string;
199
+ /** Table name */
200
+ table: string;
201
+ /**
202
+ * Access group.<br>
203
+ * When number is given, user of corresponding service group has access to the record.<br>
204
+ * User cannot set access_group number higher then the accounts service group.<br>
205
+ * When 'private' is given, record is private.
206
+ */
207
+ access_group: number | 'private';
208
+ /**
209
+ * Subscription group to allow access.<br>
210
+ * When value is given, the record is only accessable to user who is subscribed the corresponding group.
211
+ */
212
+ subscription_group: number;
213
+ /**
214
+ * Record id to reference.<br>
215
+ * If the reference record is private or subscription record, user must have access.<br>
216
+ * When the subscription or private record is referenced,
217
+ * the record does not get uploaded to the source subscription table since subscription record is only uploaded to the uploaders subscription table.<br>
218
+ * In other words, if you upload a record with reference, with given subscription group number,
219
+ * users wont be able to query all referenced record from the source since some of the referenced records will be in each individual subscription table.<br>
220
+ * If record is referencing a private record and uploaded as private,
221
+ * Any user who has access to the referenced record will also have access to all private referencing records.
222
+ */
223
+ reference?: string;
224
+ index: {
225
+ /** Index name. When ending with period, searches for nested key names ex) director. */
226
+ name: string;
227
+ /** Index value */
228
+ value: string | number | boolean;
229
+ };
230
+ /** Tags */
231
+ tags?: string | string[];
232
+ config?: {
233
+ /** Limits possible number of references. If 0 is given, record cannot be referenced. */
234
+ reference_limit?: number;
235
+ /** When true, allows users to upload multiple record that references the current record. */
236
+ allow_multiple_reference?: boolean;
237
+ /** List of user id to allow private access. */
238
+ private_access?: string | string[];
239
+ };
240
+ };
241
+
242
+ export type RecordData = {
243
+ /** Record id */
244
+ record_id: string;
245
+ /** Table name of the record */
246
+ table: string;
247
+ /** Record access group */
248
+ access_group: number | 'private';
249
+ subscription: {
250
+ /** Subscription id */
251
+ user_id: string;
252
+ /** Subscription group */
253
+ group: number;
254
+ };
255
+ /** Uploaded timestamp */
256
+ uploaded: number;
257
+ /** User id of the record owner */
258
+ user_id: string;
259
+ /** Updated timestamp */
260
+ updated: number;
261
+ /** Number of record referencing this record. */
262
+ referenced_count: number;
263
+ config: {
264
+ /** Allows multiple reference if true. */
265
+ allow_multi_reference: boolean;
266
+ /** Allows referencing if true. */
267
+ reference_limit?: number;
268
+ /** List of user id that has private access */
269
+ private_access?: string[];
270
+ };
271
+ /** Record id that the record is referencing. */
272
+ reference?: string;
273
+ /** Data of the record */
274
+ data?: any;
275
+ index?: {
276
+ /** Name of the index */
277
+ name: string;
278
+ /** Value of the index */
279
+ value: string | number | boolean;
280
+ };
281
+ /** List of tags of the record. */
282
+ tags?: string[];
283
+ };
284
+
285
+ export type QueryParams = {
286
+ /** Index name to search. */
287
+ searchFor: string;
288
+ /** Index value to search. */
289
+ value: string | number | boolean;
290
+ /** Search condition. */
291
+ condition?: '>' | '>=' | '=' | '<' | '<=' | '!=' | 'gt' | 'gte' | 'eq' | 'lt' | 'lte' | 'ne';
292
+ /** Range of search. */
293
+ range?: string | number | boolean;
294
+ };
295
+
296
+ export type FetchOptions = {
297
+ /** Number of records to fetch per call */
298
+ limit?: number;
299
+ /** Refresh the startKey. Only works on paginated queries. */
300
+ refresh?: boolean;
301
+ /** Result in ascending order if true, decending when false. */
302
+ ascending?: boolean;
303
+ /** StartKey key object can be used to query from the certain page of fetch. If refresh is true, will overwrite startKey to start. Only works on paginated queries.*/
304
+ startKey?: Record<string, any>;
305
+ };
306
+
307
+ export type FetchResponse = {
308
+ list: any[];
309
+ startKey: Record<string, any> | 'end';
310
+ endOfList: boolean;
311
+ };
312
+
313
+ export type Service = {
314
+ /** Shows active state. 1 = active, 0 = disabled */
315
+ active: number;
316
+ /** Custom api key to use for service owners custom api. */
317
+ api_key: string;
318
+ /** Service cors for connection. */
319
+ cors: string[];
320
+ /** Service owners E-Mail. */
321
+ email: string;
322
+ /** Number of users subscribed to service E-Mail. */
323
+ email_subscribers: number;
324
+ /** Service group. 1 = free try out. 1 > paid users. */
325
+ group: number;
326
+ /** Locale of where service was created. */
327
+ locale: string;
328
+ /** Service region */
329
+ region: string;
330
+ /** Service name. */
331
+ name: string;
332
+ /** Number of newsletter subscribers. */
333
+ newsletter_subscribers: number;
334
+ /** Service id. */
335
+ service: string;
336
+ /** E-Mail template for signup confirmation. This can be changed by trigger E-Mail. */
337
+ template_activation: {
338
+ html: string;
339
+ subject: string;
340
+ };
341
+ /** E-Mail template for verification code E-Mail. This can be changed by trigger E-Mail. */
342
+ template_verification: {
343
+ html: string;
344
+ sms: string;
345
+ subject: string;
346
+ };
347
+ /** E-Mail template for welcome E-Mail that user receives after signup process. This can be changed by trigger E-Mail. */
348
+ template_welcome: {
349
+ html: string;
350
+ subject: string;
351
+ };
352
+ /** 13 digit timestamp */
353
+ timestamp: number;
354
+ /** Service owner can send email to the triggers to send newsletters, or change automated E-Mail templates. */
355
+ triggers: {
356
+ /** Sends service E-Mail to E-Mail subscribed service users. */
357
+ newsletter_signed: string;
358
+ /** Sends newsletters. */
359
+ newsletter_subscribers: string;
360
+ /** Sets template of signup confirmation and account enable E-Mail. */
361
+ template_activation: string;
362
+ /** Sets template of verification E-Mail. */
363
+ template_verification: string;
364
+ /** Sets template of welcome E-Mail. */
365
+ template_welcome: string;
366
+ };
367
+ /** Number of user in the service. */
368
+ users: number;
369
+ };
370
+
371
+ export type SubscriberGroup = {
372
+ /** User id. */
373
+ userId: string;
374
+ /** Target group number (1 ~ 9). '*' is given, will apply to all groups. */
375
+ group: number | '*';
376
+ };
377
+
378
+ export type SubscriberFetch = {
379
+ /** User id of E-Mail. Defaults to users own id. If E-Mail is given for fetch subscription, api will fetch newletter subscription.*/
380
+ userId?: string;
381
+ /** Target group number (1 ~ 9). Fetch all group if ommited. */
382
+ group: number;
383
+ /** True / False to fetch email subscribed subscriptions. If omitted, will fetch both. */
384
+ emailSubscription?: boolean;
385
+ };
@@ -0,0 +1,94 @@
1
+ import { Form, FormCallbacks } from './Types';
2
+ import SkapiError from './skapi_error';
3
+ import { sha256 } from './utils';
4
+
5
+ function formResponse() {
6
+ // wraps methods that requires form handling
7
+ return function (target: object, propertyKey: string, descriptor: PropertyDescriptor) {
8
+ const fn = descriptor.value;
9
+
10
+ descriptor.value = function (...arg: any[]) {
11
+ let form: Form | Record<string, any> = arg[0];
12
+ let option: FormCallbacks = arg?.[1] || {};
13
+
14
+ const handleResponse = (response: any) => {
15
+ if (option?.response) {
16
+ if (typeof option.response === 'function') {
17
+ // return response callback
18
+ option.response(response);
19
+ return response;
20
+ } else {
21
+ throw new SkapiError('Callback "response" should be type: function.', { code: 'INVALID_PARAMETER' });
22
+ }
23
+ }
24
+
25
+ if (!(form instanceof HTMLFormElement)) {
26
+ // return if is not form element
27
+ return response;
28
+ }
29
+
30
+ // form element action
31
+ let href = new URL(form.action);
32
+ let response_key = sha256(form.action);
33
+ let timestamp = Date.now().toString();
34
+
35
+ window.sessionStorage.setItem(response_key, JSON.stringify({ [timestamp]: response }));
36
+ href.searchParams.set(response_key, timestamp);
37
+ window.location.href = href.href;
38
+ };
39
+
40
+ let response: any;
41
+ function handleError(err: any) {
42
+ let is_err = err instanceof Error ? err : new SkapiError(err);
43
+ if (option?.onerror) {
44
+ if (typeof option.onerror === 'function') {
45
+ // onerror callback
46
+ return option.onerror(is_err);
47
+ } else {
48
+ throw new SkapiError('Callback "onerror" should be type: function.', { code: 'INVALID_PARAMETER' });
49
+ }
50
+ }
51
+
52
+ return is_err;
53
+ }
54
+
55
+ try {
56
+ // execute
57
+ response = fn.bind(this)(...arg);
58
+ }
59
+
60
+ catch (err) {
61
+ let is_err = handleError(err);
62
+ if (is_err instanceof Error) {
63
+ throw is_err;
64
+ }
65
+
66
+ return is_err;
67
+ }
68
+
69
+ if (response instanceof Promise) {
70
+ // handle promise
71
+ return new Promise((res, rej) => {
72
+ response
73
+ .then((r: any) => {
74
+ res(handleResponse(r));
75
+ })
76
+ .catch((err: any) => {
77
+ err = handleError(err);
78
+ if (err instanceof Error) {
79
+ rej(err);
80
+ } else {
81
+ res(err);
82
+ }
83
+ });
84
+ });
85
+ }
86
+
87
+ else {
88
+ return handleResponse(response);
89
+ }
90
+ };
91
+ };
92
+ }
93
+
94
+ export { formResponse };