pushwave-client 0.3.7 → 0.3.9
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 +16 -0
- package/dist/attestation/getApplicationAttestation.d.ts +1 -1
- package/dist/attestation/getApplicationAttestation.js +1 -1
- package/dist/identify/identify.d.ts +2 -0
- package/dist/identify/identify.dto.d.ts +15 -0
- package/dist/identify/identify.dto.js +2 -0
- package/dist/identify/identify.js +50 -0
- package/dist/identify/index.d.ts +2 -0
- package/dist/identify/index.js +18 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +15 -0
- package/dist/logout/index.d.ts +2 -0
- package/dist/logout/index.js +18 -0
- package/dist/logout/logout.d.ts +2 -0
- package/dist/logout/logout.dto.d.ts +11 -0
- package/dist/logout/logout.dto.js +2 -0
- package/dist/logout/logout.js +49 -0
- package/dist/register/registerPushWave.d.ts +3 -0
- package/dist/register/registerPushWave.js +15 -1
- package/dist/userAttributes/index.d.ts +2 -0
- package/dist/userAttributes/index.js +18 -0
- package/dist/userAttributes/userAttributes.d.ts +3 -0
- package/dist/userAttributes/userAttributes.dto.d.ts +24 -0
- package/dist/userAttributes/userAttributes.dto.js +2 -0
- package/dist/userAttributes/userAttributes.js +87 -0
- package/dist/utils/getApiKey.d.ts +1 -0
- package/dist/utils/getApiKey.js +12 -0
- package/dist/utils/installationId.js +2 -9
- package/dist/utils/loadSecureStore.d.ts +7 -0
- package/dist/utils/loadSecureStore.js +12 -0
- package/package.json +1 -1
- package/src/attestation/getApplicationAttestation.ts +1 -1
- package/src/identify/identify.dto.ts +17 -0
- package/src/identify/identify.ts +62 -0
- package/src/identify/index.ts +2 -0
- package/src/index.ts +46 -1
- package/src/logout/index.ts +2 -0
- package/src/logout/logout.dto.ts +12 -0
- package/src/logout/logout.ts +59 -0
- package/src/register/registerPushWave.ts +24 -1
- package/src/userAttributes/index.ts +2 -0
- package/src/userAttributes/userAttributes.dto.ts +35 -0
- package/src/userAttributes/userAttributes.ts +103 -0
- package/src/utils/getApiKey.ts +12 -0
- package/src/utils/installationId.ts +1 -13
- package/src/utils/loadSecureStore.ts +13 -0
package/README.md
CHANGED
|
@@ -76,6 +76,22 @@ export default function App() {
|
|
|
76
76
|
- Call it **once** at app startup (e.g., in `App.tsx` or a root component `useEffect`). Recalling it later is unnecessary.
|
|
77
77
|
- In `__DEV__`, the SDK may log additional info/errors (e.g., failed API calls) to help debugging.
|
|
78
78
|
|
|
79
|
+
### API surface
|
|
80
|
+
|
|
81
|
+
| Method | Description | Return |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| `init({ apiKey })` | Registers the installation (Expo token + attestation + device metadata). Persists the API key when SecureStore is available. Must be called first. | `{ success, message? }` |
|
|
84
|
+
| `identify({ userId })` | Links a `userId` to the installation. Requires `init`. | `{ success, message? }` |
|
|
85
|
+
| `setUserAttributes(attributes)` | Sets custom attributes (string \| number \| boolean \| Date \| null). Requires `init`. | `{ success, message?, mismatches? }` |
|
|
86
|
+
| `getUserAttributes()` | Fetches attributes for the current installation/user. Requires `init`. | `Record<string, AttributeValue>` (throws on error) |
|
|
87
|
+
| `logout()` | Unregisters the installation (e.g., on sign-out). Requires `init`. | `{ success, message? }` |
|
|
88
|
+
|
|
89
|
+
Tip: In production builds, ensure `PUSHWAVE_API_KEY` (or your chosen env) is injected via EAS secrets or `env` in `eas.json`, so `init` can read it at runtime.
|
|
90
|
+
|
|
91
|
+
Common pitfalls:
|
|
92
|
+
- Calling `identify`/`setUserAttributes`/`getUserAttributes`/`logout` before `init` has succeeded → initialize first.
|
|
93
|
+
- Optional peers: install `expo-secure-store` for persistent installationId and `expo-application`/`expo-device`/`expo-localization` for richer metadata if you need those fields.
|
|
94
|
+
|
|
79
95
|
---
|
|
80
96
|
|
|
81
97
|
## Dashboard
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ApplicationAttestation } from "./index";
|
|
2
|
-
export declare function getApplicationAttestation(
|
|
2
|
+
export declare function getApplicationAttestation(): Promise<ApplicationAttestation>;
|
|
@@ -4,7 +4,7 @@ exports.getApplicationAttestation = getApplicationAttestation;
|
|
|
4
4
|
const buffer_1 = require("buffer");
|
|
5
5
|
const react_native_1 = require("react-native");
|
|
6
6
|
const native_1 = require("./native");
|
|
7
|
-
async function getApplicationAttestation(
|
|
7
|
+
async function getApplicationAttestation() {
|
|
8
8
|
const { nonce, timestamp } = createNonce();
|
|
9
9
|
try {
|
|
10
10
|
if (react_native_1.Platform.OS === "android")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type IdentifyResponse = {
|
|
2
|
+
success: boolean;
|
|
3
|
+
message?: string;
|
|
4
|
+
};
|
|
5
|
+
export type IdentifyOptions = {
|
|
6
|
+
userId: string;
|
|
7
|
+
};
|
|
8
|
+
export type IdentifyDTO = {
|
|
9
|
+
userId: string;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
installationId: string;
|
|
12
|
+
platform: string;
|
|
13
|
+
appAttestation?: any;
|
|
14
|
+
environment: "development" | "production";
|
|
15
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.identify = identify;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const attestation_1 = require("../attestation");
|
|
6
|
+
const register_1 = require("../register");
|
|
7
|
+
const fetch_1 = require("../utils/fetch");
|
|
8
|
+
const pwLogger_1 = require("../utils/pwLogger");
|
|
9
|
+
const installationId_1 = require("../utils/installationId");
|
|
10
|
+
const getApiKey_1 = require("../utils/getApiKey");
|
|
11
|
+
async function identify({ userId }) {
|
|
12
|
+
const response = { success: false };
|
|
13
|
+
if (!register_1.IS_INITIALIZED) {
|
|
14
|
+
pwLogger_1.PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.identify");
|
|
15
|
+
return response;
|
|
16
|
+
}
|
|
17
|
+
let apiKey;
|
|
18
|
+
try {
|
|
19
|
+
apiKey = await (0, getApiKey_1.getApiKey)();
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
pwLogger_1.PWLogger.warn("[PushWave.identify]", e);
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
const installationId = await (0, installationId_1.getInstallationId)();
|
|
26
|
+
const appAttestation = await (0, attestation_1.getApplicationAttestation)();
|
|
27
|
+
const data = {
|
|
28
|
+
apiKey,
|
|
29
|
+
userId,
|
|
30
|
+
installationId,
|
|
31
|
+
appAttestation,
|
|
32
|
+
environment: __DEV__ ? "development" : "production",
|
|
33
|
+
platform: react_native_1.Platform.OS
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const res = await (0, fetch_1.fetchApi)("PUT", "app-users", { data });
|
|
37
|
+
return {
|
|
38
|
+
success: true,
|
|
39
|
+
message: res.message,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const e = err;
|
|
44
|
+
pwLogger_1.PWLogger.error(e.message);
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
message: e.message,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./identify"), exports);
|
|
18
|
+
__exportStar(require("./identify.dto"), exports);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { RegisterPushWaveClient, RegisterPushWaveResponse } from "./register";
|
|
2
|
+
import { IdentifyOptions, IdentifyResponse } from "./identify";
|
|
3
|
+
import { LogoutResponse } from "./logout";
|
|
4
|
+
import { GetUserAttributesResponse, SetUserAttributes, SetUserAttributesResponse } from "./userAttributes";
|
|
2
5
|
export interface PushWaveClientType {
|
|
3
6
|
init(options: RegisterPushWaveClient): Promise<RegisterPushWaveResponse>;
|
|
7
|
+
identify(options: IdentifyOptions): Promise<IdentifyResponse>;
|
|
8
|
+
logout(): Promise<LogoutResponse>;
|
|
9
|
+
setUserAttributes(options: SetUserAttributes): Promise<SetUserAttributesResponse>;
|
|
10
|
+
getUserAttributes(): Promise<GetUserAttributesResponse>;
|
|
4
11
|
}
|
|
5
12
|
declare const PushWaveClient: PushWaveClientType;
|
|
6
13
|
export default PushWaveClient;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const register_1 = require("./register");
|
|
4
|
+
const identify_1 = require("./identify");
|
|
5
|
+
const logout_1 = require("./logout");
|
|
6
|
+
const userAttributes_1 = require("./userAttributes");
|
|
4
7
|
const PushWaveClient = {
|
|
5
8
|
init(options) {
|
|
6
9
|
return (0, register_1.registerPushWave)(options);
|
|
7
10
|
},
|
|
11
|
+
identify(options) {
|
|
12
|
+
return (0, identify_1.identify)(options);
|
|
13
|
+
},
|
|
14
|
+
logout() {
|
|
15
|
+
return (0, logout_1.logout)();
|
|
16
|
+
},
|
|
17
|
+
setUserAttributes(options) {
|
|
18
|
+
return (0, userAttributes_1.setUserAttributes)(options);
|
|
19
|
+
},
|
|
20
|
+
getUserAttributes() {
|
|
21
|
+
return (0, userAttributes_1.getUserAttributes)();
|
|
22
|
+
},
|
|
8
23
|
};
|
|
9
24
|
exports.default = PushWaveClient;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./logout"), exports);
|
|
18
|
+
__exportStar(require("./logout.dto"), exports);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logout = logout;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const attestation_1 = require("../attestation");
|
|
6
|
+
const register_1 = require("../register");
|
|
7
|
+
const installationId_1 = require("../utils/installationId");
|
|
8
|
+
const pwLogger_1 = require("../utils/pwLogger");
|
|
9
|
+
const fetch_1 = require("../utils/fetch");
|
|
10
|
+
const getApiKey_1 = require("../utils/getApiKey");
|
|
11
|
+
async function logout() {
|
|
12
|
+
const response = { success: false };
|
|
13
|
+
if (!register_1.IS_INITIALIZED) {
|
|
14
|
+
pwLogger_1.PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.logout");
|
|
15
|
+
return response;
|
|
16
|
+
}
|
|
17
|
+
let apiKey;
|
|
18
|
+
try {
|
|
19
|
+
apiKey = await (0, getApiKey_1.getApiKey)();
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
pwLogger_1.PWLogger.warn("[PushWave.logout]", e);
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
const installationId = await (0, installationId_1.getInstallationId)();
|
|
26
|
+
const appAttestation = await (0, attestation_1.getApplicationAttestation)();
|
|
27
|
+
const data = {
|
|
28
|
+
apiKey,
|
|
29
|
+
installationId,
|
|
30
|
+
appAttestation,
|
|
31
|
+
environment: __DEV__ ? "development" : "production",
|
|
32
|
+
platform: react_native_1.Platform.OS
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
const res = await (0, fetch_1.fetchApi)("POST", "app-installations/logout", { data });
|
|
36
|
+
return {
|
|
37
|
+
success: true,
|
|
38
|
+
message: res.message,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const e = err;
|
|
43
|
+
pwLogger_1.PWLogger.error(e.message);
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
message: e.message,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { RegisterPushWaveClient, RegisterPushWaveResponse } from "./registerPushWave.dto";
|
|
2
|
+
export declare var IS_INITIALIZED: boolean;
|
|
3
|
+
export declare const API_STORAGE_KEY = "pushwave-api-storage-key";
|
|
4
|
+
export declare var CACHE_API_KEY: string | false;
|
|
2
5
|
export declare function registerPushWave({ apiKey }: RegisterPushWaveClient): Promise<RegisterPushWaveResponse>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CACHE_API_KEY = exports.API_STORAGE_KEY = exports.IS_INITIALIZED = void 0;
|
|
3
4
|
exports.registerPushWave = registerPushWave;
|
|
4
5
|
const expoToken_1 = require("../utils/expoToken");
|
|
5
6
|
const react_native_1 = require("react-native");
|
|
@@ -9,6 +10,10 @@ const index_1 = require("../attestation/index");
|
|
|
9
10
|
const fetch_1 = require("../utils/fetch");
|
|
10
11
|
const installationId_1 = require("../utils/installationId");
|
|
11
12
|
const collectDeviceMetaData_1 = require("../utils/collectDeviceMetaData");
|
|
13
|
+
const loadSecureStore_1 = require("../utils/loadSecureStore");
|
|
14
|
+
exports.IS_INITIALIZED = false;
|
|
15
|
+
exports.API_STORAGE_KEY = "pushwave-api-storage-key";
|
|
16
|
+
exports.CACHE_API_KEY = false;
|
|
12
17
|
async function registerPushWave({ apiKey }) {
|
|
13
18
|
const OS = react_native_1.Platform.OS;
|
|
14
19
|
if ((0, apiKeyCheck_1.isSecretKey)(apiKey)) {
|
|
@@ -24,7 +29,7 @@ async function registerPushWave({ apiKey }) {
|
|
|
24
29
|
message: "[PushWaveClient] Error: " + message
|
|
25
30
|
};
|
|
26
31
|
}
|
|
27
|
-
const appAttestation = await (0, index_1.getApplicationAttestation)(
|
|
32
|
+
const appAttestation = await (0, index_1.getApplicationAttestation)();
|
|
28
33
|
if (appAttestation.status === "disabled")
|
|
29
34
|
pwLogger_1.PWLogger.warn(`(${react_native_1.Platform.OS}) could not get attestation: ${appAttestation.reason}`);
|
|
30
35
|
const path = "expo-tokens";
|
|
@@ -45,8 +50,13 @@ async function registerPushWave({ apiKey }) {
|
|
|
45
50
|
osVersion,
|
|
46
51
|
timezone
|
|
47
52
|
};
|
|
53
|
+
const SecureStore = (0, loadSecureStore_1.loadSecureStore)();
|
|
48
54
|
try {
|
|
49
55
|
const res = await (0, fetch_1.fetchApi)("PUT", path, { data: options });
|
|
56
|
+
exports.CACHE_API_KEY = apiKey;
|
|
57
|
+
if (SecureStore)
|
|
58
|
+
await SecureStore.setItemAsync(exports.API_STORAGE_KEY, apiKey);
|
|
59
|
+
exports.IS_INITIALIZED = true;
|
|
50
60
|
return {
|
|
51
61
|
success: true,
|
|
52
62
|
message: res.message,
|
|
@@ -54,6 +64,10 @@ async function registerPushWave({ apiKey }) {
|
|
|
54
64
|
}
|
|
55
65
|
catch (err) {
|
|
56
66
|
const e = err;
|
|
67
|
+
exports.CACHE_API_KEY = false;
|
|
68
|
+
if (SecureStore)
|
|
69
|
+
await SecureStore.deleteItemAsync(exports.API_STORAGE_KEY);
|
|
70
|
+
exports.IS_INITIALIZED = false;
|
|
57
71
|
pwLogger_1.PWLogger.error(e.message);
|
|
58
72
|
return {
|
|
59
73
|
success: false,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./userAttributes"), exports);
|
|
18
|
+
__exportStar(require("./userAttributes.dto"), exports);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { GetUserAttributesResponse, SetUserAttributes, SetUserAttributesResponse } from "./userAttributes.dto";
|
|
2
|
+
export declare function setUserAttributes(attributes: SetUserAttributes): Promise<SetUserAttributesResponse>;
|
|
3
|
+
export declare function getUserAttributes(): Promise<GetUserAttributesResponse>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type AttributeValue = string | number | boolean | Date | null;
|
|
2
|
+
export type SetUserAttributes = Record<string, AttributeValue>;
|
|
3
|
+
export type SetUserAttributesResponse = {
|
|
4
|
+
success: boolean;
|
|
5
|
+
message?: string;
|
|
6
|
+
mismatches?: string;
|
|
7
|
+
};
|
|
8
|
+
export type SetUserAttributesDTO = {
|
|
9
|
+
apiKey: string;
|
|
10
|
+
installationId: string;
|
|
11
|
+
platform: string;
|
|
12
|
+
appAttestation?: any;
|
|
13
|
+
environment: "development" | "production";
|
|
14
|
+
attributes: SetUserAttributes;
|
|
15
|
+
};
|
|
16
|
+
export type GetUserAttributes = Record<string, AttributeValue>;
|
|
17
|
+
export type GetUserAttributesResponse = GetUserAttributes;
|
|
18
|
+
export type GetUserAttributesDTO = {
|
|
19
|
+
apiKey: string;
|
|
20
|
+
installationId: string;
|
|
21
|
+
platform: string;
|
|
22
|
+
appAttestation?: any;
|
|
23
|
+
environment: "development" | "production";
|
|
24
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setUserAttributes = setUserAttributes;
|
|
4
|
+
exports.getUserAttributes = getUserAttributes;
|
|
5
|
+
const react_native_1 = require("react-native");
|
|
6
|
+
const attestation_1 = require("../attestation");
|
|
7
|
+
const register_1 = require("../register");
|
|
8
|
+
const getApiKey_1 = require("../utils/getApiKey");
|
|
9
|
+
const installationId_1 = require("../utils/installationId");
|
|
10
|
+
const pwLogger_1 = require("../utils/pwLogger");
|
|
11
|
+
const fetch_1 = require("../utils/fetch");
|
|
12
|
+
async function setUserAttributes(attributes) {
|
|
13
|
+
const response = { success: false };
|
|
14
|
+
if (!register_1.IS_INITIALIZED) {
|
|
15
|
+
pwLogger_1.PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.setUserAttributes");
|
|
16
|
+
return response;
|
|
17
|
+
}
|
|
18
|
+
let apiKey;
|
|
19
|
+
try {
|
|
20
|
+
apiKey = await (0, getApiKey_1.getApiKey)();
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
pwLogger_1.PWLogger.warn("[PushWave.setUserAttributes]", e);
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
const installationId = await (0, installationId_1.getInstallationId)();
|
|
27
|
+
const appAttestation = await (0, attestation_1.getApplicationAttestation)();
|
|
28
|
+
const data = {
|
|
29
|
+
apiKey,
|
|
30
|
+
installationId,
|
|
31
|
+
appAttestation,
|
|
32
|
+
environment: __DEV__ ? "development" : "production",
|
|
33
|
+
platform: react_native_1.Platform.OS,
|
|
34
|
+
attributes
|
|
35
|
+
};
|
|
36
|
+
try {
|
|
37
|
+
const res = await (0, fetch_1.fetchApi)("PATCH", "app-users/me/attributes", { data });
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
message: res.message,
|
|
41
|
+
mismatches: res.mismatches
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const e = err;
|
|
46
|
+
pwLogger_1.PWLogger.error(e.message);
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
message: e.message,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function getUserAttributes() {
|
|
54
|
+
if (!register_1.IS_INITIALIZED) {
|
|
55
|
+
const msg = `PushWaveClient.init({ apiKey }) must be called before PushWaveClient.getUserAttributes`;
|
|
56
|
+
pwLogger_1.PWLogger.warn(msg);
|
|
57
|
+
throw new Error(msg);
|
|
58
|
+
}
|
|
59
|
+
let apiKey;
|
|
60
|
+
try {
|
|
61
|
+
apiKey = await (0, getApiKey_1.getApiKey)();
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
const msg = `[PushWave.getUserAttributes] ${e}`;
|
|
65
|
+
pwLogger_1.PWLogger.warn(msg);
|
|
66
|
+
throw new Error(msg);
|
|
67
|
+
}
|
|
68
|
+
const installationId = await (0, installationId_1.getInstallationId)();
|
|
69
|
+
const appAttestation = await (0, attestation_1.getApplicationAttestation)();
|
|
70
|
+
const data = {
|
|
71
|
+
apiKey,
|
|
72
|
+
installationId,
|
|
73
|
+
appAttestation,
|
|
74
|
+
environment: __DEV__ ? "development" : "production",
|
|
75
|
+
platform: react_native_1.Platform.OS
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
const res = await (0, fetch_1.fetchApi)("POST", "app-users/me/attributes", { data });
|
|
79
|
+
return res.attributes ?? {};
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const e = err;
|
|
83
|
+
const msg = e.message;
|
|
84
|
+
pwLogger_1.PWLogger.error(msg);
|
|
85
|
+
throw new Error(msg);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getApiKey(): Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getApiKey = getApiKey;
|
|
4
|
+
const register_1 = require("../register");
|
|
5
|
+
const loadSecureStore_1 = require("./loadSecureStore");
|
|
6
|
+
async function getApiKey() {
|
|
7
|
+
const SecureStore = (0, loadSecureStore_1.loadSecureStore)();
|
|
8
|
+
const apiKey = SecureStore ? await SecureStore.getItemAsync(register_1.API_STORAGE_KEY) : register_1.CACHE_API_KEY;
|
|
9
|
+
if (!apiKey)
|
|
10
|
+
throw new Error("Unable to retrieve API key.");
|
|
11
|
+
return apiKey;
|
|
12
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getInstallationId = void 0;
|
|
4
|
+
const loadSecureStore_1 = require("./loadSecureStore");
|
|
4
5
|
const pwLogger_1 = require("./pwLogger");
|
|
5
6
|
const STORAGE_KEY = "pushwave-installation-id";
|
|
6
7
|
let cachedId = null;
|
|
@@ -28,18 +29,10 @@ const generateId = () => {
|
|
|
28
29
|
hex.slice(20)
|
|
29
30
|
].join("-");
|
|
30
31
|
};
|
|
31
|
-
const loadSecureStore = () => {
|
|
32
|
-
try {
|
|
33
|
-
return require("expo-secure-store");
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
32
|
const getInstallationId = async () => {
|
|
40
33
|
if (cachedId)
|
|
41
34
|
return cachedId;
|
|
42
|
-
const SecureStore = loadSecureStore();
|
|
35
|
+
const SecureStore = (0, loadSecureStore_1.loadSecureStore)();
|
|
43
36
|
if (SecureStore) {
|
|
44
37
|
try {
|
|
45
38
|
const existing = await SecureStore.getItemAsync(STORAGE_KEY);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type SecureStoreModule = {
|
|
2
|
+
getItemAsync(key: string): Promise<string | null>;
|
|
3
|
+
setItemAsync(key: string, value: string): Promise<void>;
|
|
4
|
+
deleteItemAsync(key: string): Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export declare const loadSecureStore: () => SecureStoreModule | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadSecureStore = void 0;
|
|
4
|
+
const loadSecureStore = () => {
|
|
5
|
+
try {
|
|
6
|
+
return require("expo-secure-store");
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
exports.loadSecureStore = loadSecureStore;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import { Platform } from "react-native";
|
|
|
3
3
|
import { getAndroidIntegrityToken, getDeviceCheckToken } from "./native";
|
|
4
4
|
import { ApplicationAttestation, AndroidAttestationPayload, DisabledAttestation, IosAttestationPayload } from "./index";
|
|
5
5
|
|
|
6
|
-
export async function getApplicationAttestation(
|
|
6
|
+
export async function getApplicationAttestation(): Promise<ApplicationAttestation> {
|
|
7
7
|
const { nonce, timestamp } = createNonce();
|
|
8
8
|
|
|
9
9
|
try {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type IdentifyResponse = {
|
|
2
|
+
success: boolean;
|
|
3
|
+
message?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type IdentifyOptions = {
|
|
7
|
+
userId: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type IdentifyDTO = {
|
|
11
|
+
userId: string;
|
|
12
|
+
apiKey: string;
|
|
13
|
+
installationId: string;
|
|
14
|
+
platform: string;
|
|
15
|
+
appAttestation?: any;
|
|
16
|
+
environment: "development" | "production",
|
|
17
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
import { getApplicationAttestation } from "../attestation";
|
|
3
|
+
import { API_STORAGE_KEY, CACHE_API_KEY, IS_INITIALIZED } from "../register";
|
|
4
|
+
import { fetchApi } from "../utils/fetch";
|
|
5
|
+
import { loadSecureStore } from "../utils/loadSecureStore";
|
|
6
|
+
import { PWLogger } from "../utils/pwLogger";
|
|
7
|
+
import { IdentifyDTO, IdentifyOptions, IdentifyResponse } from "./identify.dto";
|
|
8
|
+
import { getInstallationId } from "../utils/installationId";
|
|
9
|
+
import { getApiKey } from "../utils/getApiKey";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Link a userId to the current installation. Requires a successful registerPushWave/init call.
|
|
13
|
+
*/
|
|
14
|
+
export async function identify({ userId }: IdentifyOptions): Promise<IdentifyResponse> {
|
|
15
|
+
|
|
16
|
+
const response: IdentifyResponse = { success: false }
|
|
17
|
+
|
|
18
|
+
if (!IS_INITIALIZED) {
|
|
19
|
+
|
|
20
|
+
PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.identify");
|
|
21
|
+
|
|
22
|
+
return response;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let apiKey;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
apiKey = await getApiKey();
|
|
29
|
+
} catch (e) {
|
|
30
|
+
PWLogger.warn("[PushWave.identify]", e);
|
|
31
|
+
return response;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const installationId = await getInstallationId();
|
|
35
|
+
const appAttestation = await getApplicationAttestation();
|
|
36
|
+
|
|
37
|
+
const data: IdentifyDTO = {
|
|
38
|
+
apiKey,
|
|
39
|
+
userId,
|
|
40
|
+
installationId,
|
|
41
|
+
appAttestation,
|
|
42
|
+
environment: __DEV__ ? "development" : "production",
|
|
43
|
+
platform: Platform.OS
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const res: IdentifyResponse = await fetchApi("PUT", "app-users", { data })
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
message: res.message,
|
|
51
|
+
};
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const e = err as Error;
|
|
54
|
+
|
|
55
|
+
PWLogger.error(e.message);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
message: e.message,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,58 @@
|
|
|
1
1
|
import { registerPushWave, RegisterPushWaveClient, RegisterPushWaveResponse } from "./register";
|
|
2
|
+
import { identify, IdentifyOptions, IdentifyResponse } from "./identify";
|
|
3
|
+
import { LogoutResponse, logout } from "./logout";
|
|
4
|
+
import { getUserAttributes, GetUserAttributesDTO, GetUserAttributesResponse, setUserAttributes, SetUserAttributes, SetUserAttributesResponse } from "./userAttributes";
|
|
2
5
|
|
|
3
6
|
export interface PushWaveClientType {
|
|
7
|
+
/**
|
|
8
|
+
* Initialize PushWave for this installation. Must be called once at app startup.
|
|
9
|
+
* - Requests push permissions + Expo push token.
|
|
10
|
+
* - Collects device/app metadata and attestation.
|
|
11
|
+
* - Caches the API key (SecureStore when available) and marks the client initialized.
|
|
12
|
+
*/
|
|
4
13
|
init(options: RegisterPushWaveClient): Promise<RegisterPushWaveResponse>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Attach a userId to the current installation for targeting/analytics.
|
|
17
|
+
* Requires `init` to have run successfully in this session.
|
|
18
|
+
*/
|
|
19
|
+
identify(options: IdentifyOptions): Promise<IdentifyResponse>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Unlink the current installation from the backend (e.g., on logout).
|
|
23
|
+
* Requires `init` to have run successfully in this session.
|
|
24
|
+
*/
|
|
25
|
+
logout(): Promise<LogoutResponse>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Set custom attributes for the current user/installation.
|
|
29
|
+
* Requires `init` to have run successfully in this session.
|
|
30
|
+
*/
|
|
31
|
+
setUserAttributes(options: SetUserAttributes): Promise<SetUserAttributesResponse>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Fetch stored attributes for the current user/installation.
|
|
35
|
+
* Requires `init` to have run successfully in this session.
|
|
36
|
+
*/
|
|
37
|
+
getUserAttributes(): Promise<GetUserAttributesResponse>;
|
|
5
38
|
}
|
|
6
39
|
|
|
7
40
|
const PushWaveClient: PushWaveClientType = {
|
|
8
41
|
init(options) {
|
|
9
42
|
return registerPushWave(options);
|
|
10
43
|
},
|
|
44
|
+
identify(options) {
|
|
45
|
+
return identify(options)
|
|
46
|
+
},
|
|
47
|
+
logout() {
|
|
48
|
+
return logout();
|
|
49
|
+
},
|
|
50
|
+
setUserAttributes(options) {
|
|
51
|
+
return setUserAttributes(options)
|
|
52
|
+
},
|
|
53
|
+
getUserAttributes() {
|
|
54
|
+
return getUserAttributes();
|
|
55
|
+
},
|
|
11
56
|
};
|
|
12
57
|
|
|
13
|
-
export default PushWaveClient;
|
|
58
|
+
export default PushWaveClient;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
import { getApplicationAttestation } from "../attestation";
|
|
3
|
+
import { IS_INITIALIZED } from "../register";
|
|
4
|
+
import { getInstallationId } from "../utils/installationId";
|
|
5
|
+
import { PWLogger } from "../utils/pwLogger";
|
|
6
|
+
import { LogoutDTO, LogoutResponse } from "./logout.dto";
|
|
7
|
+
import { fetchApi } from "../utils/fetch";
|
|
8
|
+
import { getApiKey } from "../utils/getApiKey";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unregister the current installation (e.g., on user logout). Requires a successful init.
|
|
12
|
+
*/
|
|
13
|
+
export async function logout(): Promise<LogoutResponse> {
|
|
14
|
+
const response: LogoutResponse = { success: false }
|
|
15
|
+
|
|
16
|
+
if (!IS_INITIALIZED) {
|
|
17
|
+
|
|
18
|
+
PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.logout");
|
|
19
|
+
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let apiKey;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
apiKey = await getApiKey();
|
|
27
|
+
} catch (e) {
|
|
28
|
+
PWLogger.warn("[PushWave.logout]", e);
|
|
29
|
+
return response;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const installationId = await getInstallationId();
|
|
33
|
+
const appAttestation = await getApplicationAttestation();
|
|
34
|
+
|
|
35
|
+
const data: LogoutDTO = {
|
|
36
|
+
apiKey,
|
|
37
|
+
installationId,
|
|
38
|
+
appAttestation,
|
|
39
|
+
environment: __DEV__ ? "development" : "production",
|
|
40
|
+
platform: Platform.OS
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const res: LogoutResponse = await fetchApi("POST", "app-installations/logout", { data })
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
message: res.message,
|
|
48
|
+
};
|
|
49
|
+
} catch (err) {
|
|
50
|
+
const e = err as Error;
|
|
51
|
+
|
|
52
|
+
PWLogger.error(e.message);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
success: false,
|
|
56
|
+
message: e.message,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -7,7 +7,18 @@ import { getApplicationAttestation } from "../attestation/index";
|
|
|
7
7
|
import { fetchApi } from "../utils/fetch";
|
|
8
8
|
import { getInstallationId } from "../utils/installationId";
|
|
9
9
|
import { collectDeviceMetaData } from "../utils/collectDeviceMetaData";
|
|
10
|
+
import { loadSecureStore } from "../utils/loadSecureStore";
|
|
10
11
|
|
|
12
|
+
export var IS_INITIALIZED: boolean = false;
|
|
13
|
+
|
|
14
|
+
export const API_STORAGE_KEY = "pushwave-api-storage-key";
|
|
15
|
+
export var CACHE_API_KEY: string | false = false;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Initialize PushWave for this installation: retrieves the Expo push token, collects
|
|
19
|
+
* attestation + device metadata, persists the API key when SecureStore is available,
|
|
20
|
+
* and caches initialization state for subsequent calls.
|
|
21
|
+
*/
|
|
11
22
|
export async function registerPushWave(
|
|
12
23
|
{ apiKey }: RegisterPushWaveClient
|
|
13
24
|
): Promise<RegisterPushWaveResponse> {
|
|
@@ -32,7 +43,7 @@ export async function registerPushWave(
|
|
|
32
43
|
}
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
const appAttestation = await getApplicationAttestation(
|
|
46
|
+
const appAttestation = await getApplicationAttestation();
|
|
36
47
|
|
|
37
48
|
if (appAttestation.status === "disabled")
|
|
38
49
|
PWLogger.warn(`(${Platform.OS}) could not get attestation: ${appAttestation.reason}`);
|
|
@@ -59,9 +70,16 @@ export async function registerPushWave(
|
|
|
59
70
|
timezone
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
const SecureStore = loadSecureStore();
|
|
74
|
+
|
|
62
75
|
try {
|
|
63
76
|
const res: RegisterPushWaveResponse = await fetchApi("PUT", path, { data: options })
|
|
64
77
|
|
|
78
|
+
CACHE_API_KEY = apiKey;
|
|
79
|
+
if (SecureStore) await SecureStore.setItemAsync(API_STORAGE_KEY, apiKey);
|
|
80
|
+
|
|
81
|
+
IS_INITIALIZED = true;
|
|
82
|
+
|
|
65
83
|
return {
|
|
66
84
|
success: true,
|
|
67
85
|
message: res.message,
|
|
@@ -69,6 +87,11 @@ export async function registerPushWave(
|
|
|
69
87
|
} catch (err) {
|
|
70
88
|
const e = err as Error;
|
|
71
89
|
|
|
90
|
+
CACHE_API_KEY = false;
|
|
91
|
+
if (SecureStore) await SecureStore.deleteItemAsync(API_STORAGE_KEY);
|
|
92
|
+
|
|
93
|
+
IS_INITIALIZED = false;
|
|
94
|
+
|
|
72
95
|
PWLogger.error(e.message);
|
|
73
96
|
|
|
74
97
|
return {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type AttributeValue =
|
|
2
|
+
| string
|
|
3
|
+
| number
|
|
4
|
+
| boolean
|
|
5
|
+
| Date
|
|
6
|
+
| null
|
|
7
|
+
|
|
8
|
+
export type SetUserAttributes = Record<string, AttributeValue>
|
|
9
|
+
|
|
10
|
+
export type SetUserAttributesResponse = {
|
|
11
|
+
success: boolean;
|
|
12
|
+
message?: string;
|
|
13
|
+
mismatches?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type SetUserAttributesDTO = {
|
|
17
|
+
apiKey: string;
|
|
18
|
+
installationId: string;
|
|
19
|
+
platform: string;
|
|
20
|
+
appAttestation?: any;
|
|
21
|
+
environment: "development" | "production",
|
|
22
|
+
attributes: SetUserAttributes
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type GetUserAttributes = Record<string, AttributeValue>
|
|
26
|
+
|
|
27
|
+
export type GetUserAttributesResponse = GetUserAttributes;
|
|
28
|
+
|
|
29
|
+
export type GetUserAttributesDTO = {
|
|
30
|
+
apiKey: string;
|
|
31
|
+
installationId: string;
|
|
32
|
+
platform: string;
|
|
33
|
+
appAttestation?: any;
|
|
34
|
+
environment: "development" | "production";
|
|
35
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
import { getApplicationAttestation } from "../attestation";
|
|
3
|
+
import { IS_INITIALIZED } from "../register";
|
|
4
|
+
import { getApiKey } from "../utils/getApiKey";
|
|
5
|
+
import { getInstallationId } from "../utils/installationId";
|
|
6
|
+
import { PWLogger } from "../utils/pwLogger";
|
|
7
|
+
import { GetUserAttributesDTO, GetUserAttributesResponse, SetUserAttributes, SetUserAttributesDTO, SetUserAttributesResponse } from "./userAttributes.dto";
|
|
8
|
+
import { fetchApi } from "../utils/fetch";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Set custom attributes for the current user/installation. Requires a successful init.
|
|
12
|
+
*/
|
|
13
|
+
export async function setUserAttributes(attributes: SetUserAttributes): Promise<SetUserAttributesResponse> {
|
|
14
|
+
const response: SetUserAttributesResponse = { success: false }
|
|
15
|
+
|
|
16
|
+
if (!IS_INITIALIZED) {
|
|
17
|
+
|
|
18
|
+
PWLogger.warn("PushWaveClient.init({ apiKey }) must be called before PushWaveClient.setUserAttributes");
|
|
19
|
+
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let apiKey;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
apiKey = await getApiKey();
|
|
27
|
+
} catch (e) {
|
|
28
|
+
PWLogger.warn("[PushWave.setUserAttributes]", e);
|
|
29
|
+
return response;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const installationId = await getInstallationId();
|
|
33
|
+
const appAttestation = await getApplicationAttestation();
|
|
34
|
+
|
|
35
|
+
const data: SetUserAttributesDTO = {
|
|
36
|
+
apiKey,
|
|
37
|
+
installationId,
|
|
38
|
+
appAttestation,
|
|
39
|
+
environment: __DEV__ ? "development" : "production",
|
|
40
|
+
platform: Platform.OS,
|
|
41
|
+
attributes
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const res: SetUserAttributesResponse = await fetchApi("PATCH", "app-users/me/attributes", { data })
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
message: res.message,
|
|
49
|
+
mismatches: res.mismatches
|
|
50
|
+
};
|
|
51
|
+
} catch (err) {
|
|
52
|
+
const e = err as Error;
|
|
53
|
+
|
|
54
|
+
PWLogger.error(e.message);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
success: false,
|
|
58
|
+
message: e.message,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Retrieve attributes for the current user/installation. Requires a successful init.
|
|
65
|
+
*/
|
|
66
|
+
export async function getUserAttributes(): Promise<GetUserAttributesResponse> {
|
|
67
|
+
if (!IS_INITIALIZED) {
|
|
68
|
+
const msg = `PushWaveClient.init({ apiKey }) must be called before PushWaveClient.getUserAttributes`
|
|
69
|
+
PWLogger.warn(msg);
|
|
70
|
+
throw new Error(msg);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let apiKey;
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
apiKey = await getApiKey();
|
|
77
|
+
} catch (e) {
|
|
78
|
+
const msg = `[PushWave.getUserAttributes] ${e}`
|
|
79
|
+
PWLogger.warn(msg);
|
|
80
|
+
throw new Error(msg);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const installationId = await getInstallationId();
|
|
84
|
+
const appAttestation = await getApplicationAttestation();
|
|
85
|
+
|
|
86
|
+
const data: GetUserAttributesDTO = {
|
|
87
|
+
apiKey,
|
|
88
|
+
installationId,
|
|
89
|
+
appAttestation,
|
|
90
|
+
environment: __DEV__ ? "development" : "production",
|
|
91
|
+
platform: Platform.OS
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const res: { attributes: GetUserAttributesResponse } = await fetchApi("POST", "app-users/me/attributes", { data })
|
|
96
|
+
return res.attributes ?? {};
|
|
97
|
+
} catch (err) {
|
|
98
|
+
const e = err as Error;
|
|
99
|
+
const msg = e.message;
|
|
100
|
+
PWLogger.error(msg);
|
|
101
|
+
throw new Error(msg);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { API_STORAGE_KEY, CACHE_API_KEY } from "../register";
|
|
2
|
+
import { loadSecureStore } from "./loadSecureStore";
|
|
3
|
+
|
|
4
|
+
export async function getApiKey(): Promise<string> {
|
|
5
|
+
const SecureStore = loadSecureStore();
|
|
6
|
+
|
|
7
|
+
const apiKey = SecureStore ? await SecureStore.getItemAsync(API_STORAGE_KEY) : CACHE_API_KEY;
|
|
8
|
+
|
|
9
|
+
if (!apiKey) throw new Error("Unable to retrieve API key.")
|
|
10
|
+
|
|
11
|
+
return apiKey;
|
|
12
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loadSecureStore } from "./loadSecureStore";
|
|
1
2
|
import { PWLogger } from "./pwLogger";
|
|
2
3
|
|
|
3
4
|
const STORAGE_KEY = "pushwave-installation-id";
|
|
@@ -5,11 +6,6 @@ const STORAGE_KEY = "pushwave-installation-id";
|
|
|
5
6
|
let cachedId: string | null = null;
|
|
6
7
|
let warnedMissingSecureStore = false;
|
|
7
8
|
|
|
8
|
-
type SecureStoreModule = {
|
|
9
|
-
getItemAsync(key: string): Promise<string | null>;
|
|
10
|
-
setItemAsync(key: string, value: string): Promise<void>;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
9
|
const generateId = (): string => {
|
|
14
10
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
15
11
|
return crypto.randomUUID();
|
|
@@ -35,14 +31,6 @@ const generateId = (): string => {
|
|
|
35
31
|
].join("-");
|
|
36
32
|
};
|
|
37
33
|
|
|
38
|
-
const loadSecureStore = (): SecureStoreModule | null => {
|
|
39
|
-
try {
|
|
40
|
-
return require("expo-secure-store") as SecureStoreModule;
|
|
41
|
-
} catch (err) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
34
|
export const getInstallationId = async (): Promise<string> => {
|
|
47
35
|
if (cachedId) return cachedId;
|
|
48
36
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type SecureStoreModule = {
|
|
2
|
+
getItemAsync(key: string): Promise<string | null>;
|
|
3
|
+
setItemAsync(key: string, value: string): Promise<void>;
|
|
4
|
+
deleteItemAsync(key: string): Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const loadSecureStore = (): SecureStoreModule | null => {
|
|
8
|
+
try {
|
|
9
|
+
return require("expo-secure-store") as SecureStoreModule;
|
|
10
|
+
} catch (err) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
};
|