gap-nodejs-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import Gap from "./src/index";
2
+
3
+ (function test() {
4
+
5
+ })();
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "gap-nodejs-sdk",
3
+ "version": "1.0.0",
4
+ "description": "GCI App Platform Library for Node",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1",
9
+ "build": "tsc",
10
+ "lint": "eslint '**/*.{ts,tsx}' --max-warnings 0",
11
+ "clean": "rimraf ./dist tsconfig.tsbuildinfo"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://gitlab.dtsmart.vn/gap/gap-nodejs-sdk.git"
16
+ },
17
+ "author": "TanNX",
18
+ "license": "ISC",
19
+ "devDependencies": {
20
+ "rimraf": "^3.0.2",
21
+ "typescript": "^4.7.2"
22
+ },
23
+ "dependencies": {
24
+ "tslib": "^2.4.0"
25
+ }
26
+ }
@@ -0,0 +1,33 @@
1
+ import {
2
+ PlatformExecutor,
3
+ MiniAppBridge,
4
+ Callback,
5
+ mabMessageQueue,
6
+ } from '../common_bridge';
7
+ import { Platform } from '../types/platform';
8
+
9
+ /* tslint:disable:no-any */
10
+ let uniqueId = Math.random();
11
+
12
+ class AndroidExecutor implements PlatformExecutor {
13
+ execEvents(event) {
14
+ (window as any).dispatchEvent(event);
15
+ }
16
+ exec(action, param, onSuccess, onError) {
17
+ const callback = {} as Callback;
18
+ callback.onSuccess = onSuccess;
19
+ callback.onError = onError;
20
+ callback.id = String(++uniqueId);
21
+ mabMessageQueue.unshift(callback);
22
+
23
+ (window as any).MiniAppAndroid.postMessage(
24
+ JSON.stringify({ action, param, id: callback.id })
25
+ );
26
+ }
27
+
28
+ getPlatform(): string {
29
+ return Platform.ANDROID;
30
+ }
31
+ }
32
+
33
+ (window as any).MiniAppBridge = new MiniAppBridge(new AndroidExecutor());
File without changes
@@ -0,0 +1,38 @@
1
+ export declare type LoginInput = {
2
+ username: string,
3
+ password: string,
4
+ };
5
+
6
+ export declare type AppConfig = {
7
+ /**
8
+ * Title app.
9
+ */
10
+ title?: string;
11
+ /**
12
+ * 0: Default | 1: Sensor | 2: Force portrait | 3: Force landscape
13
+ */
14
+ orientation?: 'auto' | 'portrait' | 'landscape';
15
+ /**
16
+ * Color.
17
+ */
18
+ headerColor?: null | string;
19
+ /**
20
+ * Text Color.
21
+ */
22
+ textColor?: null | string;
23
+ /**
24
+ * Status bar Color.
25
+ */
26
+ statusBarColor?: null | string;
27
+ /**
28
+ * Left button.
29
+ */
30
+ leftButton?: 'none' | 'back' | 'home' | 'both';
31
+ };
32
+
33
+ export declare type CommonRequest = {
34
+ channel: string,
35
+ type: string,
36
+ method: string,
37
+ data?: string,
38
+ }
@@ -0,0 +1,36 @@
1
+ import { GapError } from "src/error"
2
+
3
+ export declare type ResponseSuccess = {
4
+ channel: string,
5
+ type: string,
6
+ method: string,
7
+ data: string
8
+ }
9
+
10
+ export declare type ResponseError = {
11
+ error: object | GapError | string,
12
+ }
13
+
14
+ export declare type SystemInfo = {
15
+ version: string,
16
+ apiVersion: string
17
+ }
18
+
19
+ export declare type BusinessInfo = {
20
+ name: string,
21
+ shortName: string,
22
+ phone: string,
23
+ address: string,
24
+ countryCode: string,
25
+ city: string,
26
+ stateCode: string,
27
+ postalCode: string,
28
+ description: string,
29
+ logoImage: string,
30
+ coverImage: string
31
+ }
32
+
33
+ export declare type BusinessConfig = {
34
+ setting: object | string,
35
+ appSetting: object | string,
36
+ }
@@ -0,0 +1,14 @@
1
+ export enum GapApiVersion {
2
+ V1 = '1.0.0',
3
+ }
4
+
5
+ export enum GapHeader {
6
+ GClientId = 'G-ClientID'
7
+ }
8
+
9
+ export enum UserAgent {
10
+ IOS = 'IOS',
11
+ ANDROID = 'ANDROID',
12
+ CHROME = 'CHROME',
13
+ SAFARI = 'SAFARI',
14
+ }
@@ -0,0 +1,146 @@
1
+ /** @internal */
2
+ const mabMessageQueue: Callback[] = [];
3
+ const mabCustomEventQueue: CustomEvent[] = [];
4
+ const mabKeyboardEventQueue: CustomEvent[] = [];
5
+ export { mabMessageQueue };
6
+ export { mabCustomEventQueue };
7
+ export { mabKeyboardEventQueue };
8
+
9
+ /** @internal */
10
+ export interface Callback {
11
+ id: string;
12
+ onSuccess: (value: string) => void;
13
+ onError: (error: string) => void;
14
+ }
15
+
16
+ /** @internal */
17
+ export interface PlatformExecutor {
18
+ /**
19
+ * Method to call the native interface methods for respective platforms
20
+ * such as iOS & Android.
21
+ * @param {[string]} action Action command/interface name that native side need to execute
22
+ * @param {Object} param Object that contains request parameter values like permissions.
23
+ * For eg., {permission: 'location'}
24
+ * @param {[Function]} onSuccess Success callback function
25
+ * @param {[Function]} onError Error callback function
26
+ */
27
+ exec(
28
+ action: string,
29
+ param: object | null,
30
+ onSuccess: (value: string) => void,
31
+ onError: (error: string) => void
32
+ ): void;
33
+
34
+ execEvents(event: CustomEvent): void;
35
+
36
+ /**
37
+ * Get the platform which injects this bridge.
38
+ * @returns The platform name. It could be 'Android' or 'iOS'.
39
+ */
40
+ getPlatform(): string;
41
+ }
42
+
43
+ export class MiniAppBridge {
44
+ executor: PlatformExecutor;
45
+ platform: string;
46
+ // isSecureStorageReady = false;
47
+ // secureStorageLoadError: MiniAppError | null = null;
48
+
49
+ constructor(executor: PlatformExecutor) {
50
+ this.executor = executor;
51
+ this.platform = executor.getPlatform();
52
+
53
+ // window.addEventListener(
54
+ // MiniAppSecureStorageEvents.onReady,
55
+ // () => (this.isSecureStorageReady = true)
56
+ // );
57
+ // window.addEventListener(
58
+ // MiniAppSecureStorageEvents.onLoadError,
59
+ // (e: CustomEvent) =>
60
+ // (this.secureStorageLoadError = parseMiniAppError(e.detail.message))
61
+ // );
62
+ }
63
+
64
+ /**
65
+ * Success Callback method that will be called from native side
66
+ * to this bridge. This method will send back the value to the
67
+ * mini apps that uses promises.
68
+ * @param {[String]} messageId Message ID which will be used to get callback object from messageQueue
69
+ * @param {[String]} value Response value sent from the native on invoking the action command
70
+ */
71
+ execSuccessCallback(messageId, value) {
72
+ const queueObj = mabMessageQueue.filter(
73
+ callback => callback.id === messageId
74
+ )[0];
75
+ if (value) {
76
+ queueObj.onSuccess(value);
77
+ } else {
78
+ queueObj.onError('Unknown Error');
79
+ }
80
+ removeFromMessageQueue(queueObj);
81
+ }
82
+
83
+ /**
84
+ * Error Callback method that will be called from native side
85
+ * to this bridge. This method will send back the error message to the
86
+ * mini apps that uses promises.
87
+ * @param {[String]} messageId Message ID which will be used to get callback object from messageQueue
88
+ * @param {[String]} errorMessage Error message sent from the native on invoking the action command
89
+ */
90
+ execErrorCallback(messageId, errorMessage) {
91
+ const queueObj = mabMessageQueue.filter(
92
+ callback => callback.id === messageId
93
+ )[0];
94
+ if (!errorMessage) {
95
+ errorMessage = 'Unknown Error';
96
+ }
97
+ queueObj.onError(errorMessage);
98
+ removeFromMessageQueue(queueObj);
99
+ }
100
+ /**
101
+ * Event Callback method that will be called from native side
102
+ * to this bridge. This method will send back the value to the
103
+ * mini app that listen to this eventType.
104
+ * @param {[String]} eventType EventType which will be used to listen for the event
105
+ * @param {[String]} value Additional message sent from the native on invoking for the eventType
106
+ */
107
+ execCustomEventsCallback(eventType: string, value: string) {
108
+ const event = new CustomEvent(eventType, {
109
+ detail: { message: value },
110
+ });
111
+ let queueObj = mabCustomEventQueue.filter(
112
+ customEvent => customEvent === event
113
+ )[0];
114
+ if (!queueObj) {
115
+ if (eventType === event.type) {
116
+ removeFromEventQueue(event);
117
+ }
118
+ queueObj = event;
119
+ mabCustomEventQueue.unshift(queueObj);
120
+ }
121
+ this.executor.execEvents(queueObj);
122
+ }
123
+ }
124
+ /**
125
+ * Method to remove the callback object from the message queue after successful/error communication
126
+ * with the native application
127
+ * @param {[Object]} queueObj Queue Object that holds the references of callback information.
128
+ * @internal
129
+ */
130
+ function removeFromMessageQueue(queueObj) {
131
+ const messageObjIndex = mabMessageQueue.indexOf(queueObj);
132
+ if (messageObjIndex !== -1) {
133
+ mabMessageQueue.splice(messageObjIndex, 1);
134
+ }
135
+ }
136
+
137
+ function removeFromEventQueue(queueObj) {
138
+ const eventObjIndex = mabCustomEventQueue.indexOf(
139
+ mabCustomEventQueue.filter(
140
+ customEvent => customEvent.type === queueObj.type
141
+ )[0]
142
+ );
143
+ if (eventObjIndex !== -1) {
144
+ mabCustomEventQueue.splice(eventObjIndex, 1);
145
+ }
146
+ }
package/src/context.ts ADDED
@@ -0,0 +1,72 @@
1
+ import { GapApiVersion } from "./base-type";
2
+ import * as GapErrors from "./error";
3
+
4
+
5
+ interface ContextInterface {
6
+ API_KEY: string;
7
+ API_SECRET_KEY: string;
8
+ G_CLIENTID: string;
9
+ API_VERSION: GapApiVersion;
10
+ USER_AGENT: string;
11
+ // HOST_NAME: string;
12
+ // HOST_SCHEME?: string;
13
+ // IS_EMBEDDED_APP: boolean;
14
+ // IS_PRIVATE_APP?: boolean;
15
+ LOG_FILE?: string;
16
+ USER_AGENT_PREFIX?: string;
17
+
18
+
19
+ /**
20
+ * Sets up the GAP API Library
21
+ *
22
+ * @param params Settings to update
23
+ */
24
+ initialize(params: ContextInterface): void;
25
+
26
+ /**
27
+ * Throws error if context has not been initialized.
28
+ */
29
+ throwIfUninitialized(): void | never;
30
+
31
+ }
32
+
33
+ const Context: ContextInterface = {
34
+ API_KEY: "",
35
+ API_SECRET_KEY: "",
36
+ G_CLIENTID: "",
37
+ USER_AGENT: "",
38
+ API_VERSION: GapApiVersion.V1,
39
+ initialize: function (params: ContextInterface): void {
40
+ // Make sure that the essential params actually have content in them
41
+ const missing: string[] = [];
42
+ if (!params.API_KEY.length) {
43
+ missing.push('API_KEY');
44
+ }
45
+ if (!params.API_SECRET_KEY.length) {
46
+ missing.push('API_SECRET_KEY');
47
+ }
48
+ if (!params.API_SECRET_KEY.length) {
49
+ missing.push('G_CLIENTID');
50
+ }
51
+ if (missing.length) {
52
+ throw new GapErrors.MissingDataContextError(
53
+ `Cannot initialize Shopify API Library. Missing values for: ${missing.join(
54
+ ', '
55
+ )}`
56
+ );
57
+ }
58
+ this.API_KEY = params.API_KEY;
59
+ this.API_SECRET_KEY = params.API_SECRET_KEY;
60
+ this.G_CLIENTID = params.G_CLIENTID;
61
+ this.API_VERSION = params.API_VERSION;
62
+ },
63
+ throwIfUninitialized: function (): void {
64
+ if (!this.API_KEY || this.API_KEY.length === 0) {
65
+ throw new GapErrors.UninitializedContextError(
66
+ 'Context has not been properly initialized. Please call the .initialize() method to setup your app context object.'
67
+ );
68
+ }
69
+ },
70
+ }
71
+
72
+ export { Context, ContextInterface };
package/src/error.ts ADDED
@@ -0,0 +1,39 @@
1
+ export class GapError extends Error {
2
+ constructor(...args: any) {
3
+ super(...args);
4
+ Object.setPrototypeOf(this, new.target.prototype);
5
+ }
6
+ }
7
+
8
+ interface HttpResponseData {
9
+ code: number;
10
+ statusText: string;
11
+ body?: { [key: string]: unknown };
12
+ headers?: { [key: string]: unknown };
13
+ }
14
+ interface HttpResponseErrorParams extends HttpResponseData {
15
+ message: string;
16
+ }
17
+ export class HttpResponseError extends GapError {
18
+ readonly response: HttpResponseData;
19
+
20
+ public constructor({
21
+ message,
22
+ code,
23
+ statusText,
24
+ body,
25
+ headers,
26
+ }: HttpResponseErrorParams) {
27
+ super(message);
28
+ this.response = {
29
+ code,
30
+ statusText,
31
+ body,
32
+ headers,
33
+ };
34
+ }
35
+ }
36
+
37
+ //Detail of error for testing purpose
38
+ export class UninitializedContextError extends GapError { };
39
+ export class MissingDataContextError extends GapError { };
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { Context } from './context';
2
+ import * as NativeApp from "./native_app/index";
3
+ import * as ShopifyErrors from './error';
4
+
5
+ export const Gap = {
6
+ Context,
7
+ NativeApp,
8
+ // GciClientApi,
9
+ Errors: ShopifyErrors,
10
+ };
11
+
12
+ export default Gap;
13
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export interface InvokeEvent {
2
+ invokeEvent: () => string;
3
+ }
@@ -0,0 +1,13 @@
1
+ import * as ResponseDataType from "src/base/response_data_type";
2
+ import * as InputDataType from "src/base/input_data_type";
3
+
4
+ export default interface NativeAppInterFace {
5
+ getAppId: () => string;
6
+ login: (data?: InputDataType.LoginInput) => Promise<string>;
7
+ getLoginStatus: () => boolean;
8
+ getAccessToken: () => Promise<string | null>;
9
+ getVersion: () => string;
10
+ getSystemInfo: () => ResponseDataType.SystemInfo;
11
+ getBusinessInfo: () => ResponseDataType.BusinessInfo;
12
+ getBusinessConfig: () => ResponseDataType.BusinessConfig;
13
+ }
@@ -0,0 +1,61 @@
1
+ import {
2
+ PlatformExecutor,
3
+ MiniAppBridge,
4
+ Callback,
5
+ mabMessageQueue,
6
+ } from '../common_bridge';
7
+ import { Platform } from '../types/platform';
8
+
9
+ /* tslint:disable:no-any */
10
+ let uniqueId = Math.random();
11
+
12
+ // tslint:disable-next-line: variable-name
13
+ const GeolocationPositionError = {
14
+ PERMISSION_DENIED: 1,
15
+ POSITION_UNAVAILABLE: 2,
16
+ TIMEOUT: 3,
17
+ };
18
+
19
+ class IOSExecutor implements PlatformExecutor {
20
+ execEvents(event): void {
21
+ (window as any).dispatchEvent(event);
22
+ }
23
+ exec(action, param, onSuccess, onError) {
24
+ const callback = {} as Callback;
25
+ callback.onSuccess = onSuccess;
26
+ callback.onError = onError;
27
+ callback.id = String(++uniqueId);
28
+ mabMessageQueue.unshift(callback);
29
+
30
+ (window as any).webkit.messageHandlers.MiniAppiOS.postMessage(
31
+ JSON.stringify({ action, param, id: callback.id })
32
+ );
33
+ }
34
+
35
+ getPlatform(): string {
36
+ return Platform.IOS;
37
+ }
38
+ }
39
+
40
+ const iOSExecutor = new IOSExecutor();
41
+ (window as any).MiniAppBridge = new MiniAppBridge(iOSExecutor);
42
+
43
+ navigator.geolocation.getCurrentPosition = (success, error, options) => {
44
+ return iOSExecutor.exec(
45
+ 'getCurrentPosition',
46
+ { locationOptions: options },
47
+ value => {
48
+ try {
49
+ const parsedData = JSON.parse(value);
50
+ success(parsedData);
51
+ } catch (error) {
52
+ error({
53
+ code: GeolocationPositionError.POSITION_UNAVAILABLE,
54
+ message:
55
+ 'Failed to parse location object from MiniAppBridge: ' + error,
56
+ });
57
+ }
58
+ },
59
+ error => console.error(error)
60
+ );
61
+ };
@@ -0,0 +1,17 @@
1
+ import * as ResponseDataType from "src/base/response_data_type";
2
+ import NativeAppInterFace from "src/interface/native_app_interface";
3
+ import * as InputDataType from "src/base/input_data_type";
4
+
5
+ export class NativeApp implements NativeAppInterFace {
6
+ public getAppId() {
7
+ return "";
8
+ }
9
+ login: (data?: InputDataType.LoginInput | undefined) => Promise<string>;
10
+ getLoginStatus: () => boolean;
11
+ getAccessToken: () => Promise<string | null>;
12
+ getVersion: () => string;
13
+ getSystemInfo: () => ResponseDataType.SystemInfo;
14
+ getBusinessInfo: () => ResponseDataType.BusinessInfo;
15
+ getBusinessConfig: () => ResponseDataType.BusinessConfig;
16
+
17
+ }
@@ -0,0 +1,8 @@
1
+ /** @internal */
2
+
3
+ /** Device platform. */
4
+ export enum Platform {
5
+ ANDROID = 'Android',
6
+ IOS = 'iOS',
7
+ WEB = 'Web'
8
+ }
package/src/types.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './base-type';
package/tsconfig.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "pretty": true,
8
+ "moduleResolution": "node",
9
+ "target": "es6",
10
+ "downlevelIteration": true,
11
+ "esModuleInterop": true,
12
+ "sourceMap": false,
13
+ "noEmitOnError": false,
14
+ "experimentalDecorators": true,
15
+ "noUnusedParameters": true,
16
+ "noUnusedLocals": true,
17
+ "importHelpers": true,
18
+ "strictNullChecks": true,
19
+ "noImplicitAny": false,
20
+ "noImplicitThis": true,
21
+ "resolveJsonModule": true,
22
+ "skipLibCheck": true,
23
+ "lib": [
24
+ "dom",
25
+ "dom.iterable",
26
+ "es2015",
27
+ "es2016",
28
+ "es2017",
29
+ "es2018",
30
+ "es2019",
31
+ "es2020",
32
+ "esnext.asynciterable"
33
+ ],
34
+ "typeRoots": [
35
+ "./node_modules/@types"
36
+ ],
37
+ "outDir": "./dist",
38
+ "baseUrl": ".",
39
+ "rootDir": "src"
40
+ },
41
+ "include": [
42
+ "./src/**/*.ts",
43
+ "./src/**/*.tsx"
44
+ ],
45
+ "exclude": [
46
+ "**/*.test.ts",
47
+ "**/*.test.tsx",
48
+ "**/test/*"
49
+ ]
50
+ }