@symbiote-native/application 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/LICENSE +21 -0
- package/README.md +223 -0
- package/build/angular/index.d.ts +1 -0
- package/build/angular/index.js +4 -0
- package/build/core/application.d.ts +77 -0
- package/build/core/application.js +119 -0
- package/build/core/index.d.ts +2 -0
- package/build/core/index.js +2 -0
- package/build/core/native-module.d.ts +15 -0
- package/build/core/native-module.js +3 -0
- package/build/core/types.d.ts +17 -0
- package/build/core/types.js +16 -0
- package/build/react/index.d.ts +1 -0
- package/build/react/index.js +5 -0
- package/build/vue/index.d.ts +1 -0
- package/build/vue/index.js +4 -0
- package/build-ngc/angular/index.d.ts +1 -0
- package/build-ngc/angular/index.js +5 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/core/application.d.ts +77 -0
- package/build-ngc/core/application.js +120 -0
- package/build-ngc/core/application.js.map +1 -0
- package/build-ngc/core/index.d.ts +2 -0
- package/build-ngc/core/index.js +3 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +15 -0
- package/build-ngc/core/native-module.js +4 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/types.d.ts +17 -0
- package/build-ngc/core/types.js +17 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +12 -0
- package/package.json +107 -0
- package/src/angular/index.ts +4 -0
- package/src/core/application.test.ts +150 -0
- package/src/core/application.ts +134 -0
- package/src/core/index.ts +14 -0
- package/src/core/native-module.ts +26 -0
- package/src/core/types.ts +22 -0
- package/src/react/index.ts +5 -0
- package/src/vue/index.ts +4 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import { expoApplication } from './native-module';
|
|
3
|
+
const NATIVE_MODULE_NAME = 'expo-application';
|
|
4
|
+
/**
|
|
5
|
+
* The human-readable version of the native application that may be displayed in the app store.
|
|
6
|
+
* On Android, this is the version name set by `version` in the app config; on iOS, the
|
|
7
|
+
* `Info.plist` value for `CFBundleShortVersionString`.
|
|
8
|
+
* @example `"2.11.0"`
|
|
9
|
+
*/
|
|
10
|
+
export const nativeApplicationVersion = expoApplication.nativeApplicationVersion ?? null;
|
|
11
|
+
/**
|
|
12
|
+
* The internal build version of the native application that the app stores may use to
|
|
13
|
+
* distinguish between different binaries. On Android, this is `android.versionCode`; on iOS,
|
|
14
|
+
* the `Info.plist` value for `CFBundleVersion` (`ios.buildNumber` in the app config).
|
|
15
|
+
* @example `"114"`
|
|
16
|
+
*/
|
|
17
|
+
export const nativeBuildVersion = expoApplication.nativeBuildVersion ?? null;
|
|
18
|
+
/**
|
|
19
|
+
* The human-readable name of the application, displayed with the app's icon on the device's
|
|
20
|
+
* home screen.
|
|
21
|
+
* @example `"Expo"`, `"Yelp"`, `"Instagram"`
|
|
22
|
+
*/
|
|
23
|
+
export const applicationName = expoApplication.applicationName ?? null;
|
|
24
|
+
/**
|
|
25
|
+
* The ID of the application. On Android, this is the application ID. On iOS, this is the
|
|
26
|
+
* bundle ID.
|
|
27
|
+
* @example `"com.cocoacasts.scribbles"`, `"com.apple.Pages"`
|
|
28
|
+
*/
|
|
29
|
+
export const applicationId = expoApplication.applicationId ?? null;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the value of `Settings.Secure.ANDROID_ID` — a hexadecimal string unique to each
|
|
32
|
+
* combination of app-signing key, user, and device. The value may change if a factory reset is
|
|
33
|
+
* performed on the device or if an APK signing key changes.
|
|
34
|
+
* @example `Application.getAndroidId(); // "dd96dec43fb81c97"`
|
|
35
|
+
* @platform android
|
|
36
|
+
*/
|
|
37
|
+
export function getAndroidId() {
|
|
38
|
+
if (Platform.OS !== 'android') {
|
|
39
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'androidId');
|
|
40
|
+
}
|
|
41
|
+
if (!expoApplication.androidId) {
|
|
42
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'androidId');
|
|
43
|
+
}
|
|
44
|
+
return expoApplication.androidId;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the referrer URL of the installed app with the Install Referrer API from the Google Play
|
|
48
|
+
* Store. In practice, the referrer URL may not be a complete, absolute URL.
|
|
49
|
+
* @example `await Application.getInstallReferrerAsync(); // "utm_source=google-play&utm_medium=organic"`
|
|
50
|
+
* @platform android
|
|
51
|
+
*/
|
|
52
|
+
export async function getInstallReferrerAsync() {
|
|
53
|
+
if (!expoApplication.getInstallReferrerAsync) {
|
|
54
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getInstallReferrerAsync');
|
|
55
|
+
}
|
|
56
|
+
return expoApplication.getInstallReferrerAsync();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Gets the iOS "identifier for vendor" (IDFV) — a string ID that uniquely identifies a device to
|
|
60
|
+
* the app's vendor. May resolve `null`, in which case wait and call again later (this can happen
|
|
61
|
+
* when the device was restarted before the user unlocked it). The OS changes the vendor
|
|
62
|
+
* identifier once every app from the current vendor has been uninstalled.
|
|
63
|
+
* @example `await Application.getIosIdForVendorAsync(); // "68753A44-4D6F-1226-9C60-0050E4C00067"`
|
|
64
|
+
* @platform ios
|
|
65
|
+
*/
|
|
66
|
+
export async function getIosIdForVendorAsync() {
|
|
67
|
+
if (!expoApplication.getIosIdForVendorAsync) {
|
|
68
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getIosIdForVendorAsync');
|
|
69
|
+
}
|
|
70
|
+
return expoApplication.getIosIdForVendorAsync();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Gets the iOS application release type.
|
|
74
|
+
* @platform ios
|
|
75
|
+
*/
|
|
76
|
+
export async function getIosApplicationReleaseTypeAsync() {
|
|
77
|
+
if (!expoApplication.getApplicationReleaseTypeAsync) {
|
|
78
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getApplicationReleaseTypeAsync');
|
|
79
|
+
}
|
|
80
|
+
return expoApplication.getApplicationReleaseTypeAsync();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Gets the current Apple Push Notification (APN) service environment.
|
|
84
|
+
* @return Either `'development'` or `'production'`, or `null` on the simulator (which does not
|
|
85
|
+
* support registering with APNs).
|
|
86
|
+
* @platform ios
|
|
87
|
+
*/
|
|
88
|
+
export async function getIosPushNotificationServiceEnvironmentAsync() {
|
|
89
|
+
if (!expoApplication.getPushNotificationServiceEnvironmentAsync) {
|
|
90
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getPushNotificationServiceEnvironmentAsync');
|
|
91
|
+
}
|
|
92
|
+
return expoApplication.getPushNotificationServiceEnvironmentAsync();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Gets the time the app was installed onto the device, not counting subsequent updates. If the
|
|
96
|
+
* app is uninstalled and reinstalled, this returns the time of the reinstall.
|
|
97
|
+
* - Android: `PackageInfo.firstInstallTime`.
|
|
98
|
+
* - iOS: the `NSFileCreationDate` of the app's document root directory.
|
|
99
|
+
* @example `await Application.getInstallationTimeAsync(); // 2019-07-18T18:08:26.121Z`
|
|
100
|
+
*/
|
|
101
|
+
export async function getInstallationTimeAsync() {
|
|
102
|
+
if (!expoApplication.getInstallationTimeAsync) {
|
|
103
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getInstallationTimeAsync');
|
|
104
|
+
}
|
|
105
|
+
const installationTime = await expoApplication.getInstallationTimeAsync();
|
|
106
|
+
return new Date(installationTime);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Gets the last time the app was updated from the Google Play Store.
|
|
110
|
+
* @example `await Application.getLastUpdateTimeAsync(); // 2019-07-18T21:20:16.887Z`
|
|
111
|
+
* @platform android
|
|
112
|
+
*/
|
|
113
|
+
export async function getLastUpdateTimeAsync() {
|
|
114
|
+
if (!expoApplication.getLastUpdateTimeAsync) {
|
|
115
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getLastUpdateTimeAsync');
|
|
116
|
+
}
|
|
117
|
+
const lastUpdateTime = await expoApplication.getLastUpdateTimeAsync();
|
|
118
|
+
return new Date(lastUpdateTime);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=application.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/core/application.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { nativeApplicationVersion, nativeBuildVersion, applicationName, applicationId, getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync, getIosApplicationReleaseTypeAsync, getIosPushNotificationServiceEnvironmentAsync, getInstallationTimeAsync, getLastUpdateTimeAsync, } from './application';
|
|
2
|
+
export { ApplicationReleaseType, type PushNotificationServiceEnvironment } from './types';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { nativeApplicationVersion, nativeBuildVersion, applicationName, applicationId, getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync, getIosApplicationReleaseTypeAsync, getIosPushNotificationServiceEnvironmentAsync, getInstallationTimeAsync, getLastUpdateTimeAsync, } from './application';
|
|
2
|
+
export { ApplicationReleaseType } from './types';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,sBAAsB,EACtB,iCAAiC,EACjC,6CAA6C,EAC7C,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAA2C,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ApplicationReleaseType, PushNotificationServiceEnvironment } from './types';
|
|
2
|
+
export type INativeApplicationModule = {
|
|
3
|
+
nativeApplicationVersion?: string | null;
|
|
4
|
+
nativeBuildVersion?: string | null;
|
|
5
|
+
applicationName?: string | null;
|
|
6
|
+
applicationId?: string | null;
|
|
7
|
+
androidId?: string;
|
|
8
|
+
getInstallReferrerAsync?(): Promise<string>;
|
|
9
|
+
getIosIdForVendorAsync?(): Promise<string | null>;
|
|
10
|
+
getApplicationReleaseTypeAsync?(): Promise<ApplicationReleaseType>;
|
|
11
|
+
getPushNotificationServiceEnvironmentAsync?(): Promise<PushNotificationServiceEnvironment>;
|
|
12
|
+
getInstallationTimeAsync?(): Promise<number>;
|
|
13
|
+
getLastUpdateTimeAsync?(): Promise<number>;
|
|
14
|
+
};
|
|
15
|
+
export declare const expoApplication: INativeApplicationModule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,4BAA4B,GAAG,iBAAiB,CAAC;AAoBvD,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAChD,4BAA4B,CAC7B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The type of release for the app that is currently running.
|
|
3
|
+
* @platform ios
|
|
4
|
+
*/
|
|
5
|
+
export declare enum ApplicationReleaseType {
|
|
6
|
+
UNKNOWN = 0,
|
|
7
|
+
SIMULATOR = 1,
|
|
8
|
+
ENTERPRISE = 2,
|
|
9
|
+
DEVELOPMENT = 3,
|
|
10
|
+
AD_HOC = 4,
|
|
11
|
+
APP_STORE = 5
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Maps to the `aps-environment` key in the native target's registered entitlements.
|
|
15
|
+
* @platform ios
|
|
16
|
+
*/
|
|
17
|
+
export type PushNotificationServiceEnvironment = 'development' | 'production' | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Upstream ships two iOS-only types describing the shape of a running app build — the
|
|
2
|
+
// release channel it was built through and the current APN environment. Ported verbatim
|
|
3
|
+
// from expo-application's Application.types.ts (sdk-57).
|
|
4
|
+
/**
|
|
5
|
+
* The type of release for the app that is currently running.
|
|
6
|
+
* @platform ios
|
|
7
|
+
*/
|
|
8
|
+
export var ApplicationReleaseType;
|
|
9
|
+
(function (ApplicationReleaseType) {
|
|
10
|
+
ApplicationReleaseType[ApplicationReleaseType["UNKNOWN"] = 0] = "UNKNOWN";
|
|
11
|
+
ApplicationReleaseType[ApplicationReleaseType["SIMULATOR"] = 1] = "SIMULATOR";
|
|
12
|
+
ApplicationReleaseType[ApplicationReleaseType["ENTERPRISE"] = 2] = "ENTERPRISE";
|
|
13
|
+
ApplicationReleaseType[ApplicationReleaseType["DEVELOPMENT"] = 3] = "DEVELOPMENT";
|
|
14
|
+
ApplicationReleaseType[ApplicationReleaseType["AD_HOC"] = 4] = "AD_HOC";
|
|
15
|
+
ApplicationReleaseType[ApplicationReleaseType["APP_STORE"] = 5] = "APP_STORE";
|
|
16
|
+
})(ApplicationReleaseType || (ApplicationReleaseType = {}));
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,wFAAwF;AACxF,yDAAyD;AAEzD;;;GAGG;AACH,MAAM,CAAN,IAAY,sBAOX;AAPD,WAAY,sBAAsB;IAChC,yEAAW,CAAA;IACX,6EAAa,CAAA;IACb,+EAAc,CAAA;IACd,iFAAe,CAAA;IACf,uEAAU,CAAA;IACV,6EAAa,CAAA;AACf,CAAC,EAPW,sBAAsB,KAAtB,sBAAsB,QAOjC"}
|
package/native-link.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@symbiote-native/application",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "expo-application wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, and Angular adapters. Native app version/build/name/ID constants, the Android ID, install-referrer and install/update-time lookups, and the iOS vendor ID, release type, and push-notification-service environment.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
9
|
+
"directory": "packages/application"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/packages/application#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/OneEyed1366/symbiote-native/issues"
|
|
14
|
+
},
|
|
15
|
+
"author": "Andrey Prokopenko <psevdoproger@gmail.com>",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./build/core/index.js",
|
|
18
|
+
"module": "./build/core/index.js",
|
|
19
|
+
"types": "./build/core/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./build/core/index.d.ts",
|
|
23
|
+
"default": "./build/core/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./vue": {
|
|
26
|
+
"types": "./build/vue/index.d.ts",
|
|
27
|
+
"default": "./build/vue/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./react": {
|
|
30
|
+
"types": "./build/react/index.d.ts",
|
|
31
|
+
"default": "./build/react/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./angular": {
|
|
34
|
+
"types": "./build-ngc/angular/index.d.ts",
|
|
35
|
+
"react-native": "./build-ngc/angular/index.js",
|
|
36
|
+
"default": "./src/angular/index.ts"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"src",
|
|
41
|
+
"build",
|
|
42
|
+
"build-ngc",
|
|
43
|
+
"native-link.json"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"expo-application": "57.0.2",
|
|
50
|
+
"expo-modules-core": "57.0.5"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@symbiote-native/engine": ">=0.1.7",
|
|
54
|
+
"@angular/core": ">=20",
|
|
55
|
+
"@vue/runtime-core": "^3.5.13",
|
|
56
|
+
"react": ">=19.0.0",
|
|
57
|
+
"react-native": ">=0.86",
|
|
58
|
+
"vue": ">=3.5.0",
|
|
59
|
+
"@symbiote-native/angular": "0.6.1",
|
|
60
|
+
"@symbiote-native/react": "0.2.8",
|
|
61
|
+
"@symbiote-native/vue": "0.3.8"
|
|
62
|
+
},
|
|
63
|
+
"peerDependenciesMeta": {
|
|
64
|
+
"@symbiote-native/angular": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"@symbiote-native/react": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@symbiote-native/vue": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@angular/core": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@vue/runtime-core": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"react": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"vue": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@angular/compiler": "^22",
|
|
88
|
+
"@angular/compiler-cli": "^22",
|
|
89
|
+
"@angular/core": "^22",
|
|
90
|
+
"@types/node": "^26.0.0",
|
|
91
|
+
"@types/react": "^19.2.0",
|
|
92
|
+
"@vue/runtime-core": "^3.5.13",
|
|
93
|
+
"react": "19.2.3",
|
|
94
|
+
"typescript": "~6.0.0",
|
|
95
|
+
"@symbiote-native/angular": "0.6.1",
|
|
96
|
+
"@symbiote-native/engine": "0.1.7",
|
|
97
|
+
"@symbiote-native/react": "0.2.8",
|
|
98
|
+
"@symbiote-native/test-utils": "0.1.6",
|
|
99
|
+
"@symbiote-native/vue": "0.3.8"
|
|
100
|
+
},
|
|
101
|
+
"scripts": {
|
|
102
|
+
"typecheck": "tsc --build",
|
|
103
|
+
"clean": "rm -rf build-ngc",
|
|
104
|
+
"ng:build": "pnpm run clean && ngc -p tsconfig.angular.json",
|
|
105
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const FAKE_NATIVE_APPLICATION = {
|
|
4
|
+
nativeApplicationVersion: '2.11.0',
|
|
5
|
+
nativeBuildVersion: '114',
|
|
6
|
+
applicationName: 'Canary',
|
|
7
|
+
applicationId: 'com.symbiote.canary',
|
|
8
|
+
androidId: 'dd96dec43fb81c97',
|
|
9
|
+
getInstallReferrerAsync: vi.fn(async () => 'utm_source=google-play&utm_medium=organic'),
|
|
10
|
+
getIosIdForVendorAsync: vi.fn(async () => '68753A44-4D6F-1226-9C60-0050E4C00067'),
|
|
11
|
+
getApplicationReleaseTypeAsync: vi.fn(async () => 5),
|
|
12
|
+
getPushNotificationServiceEnvironmentAsync: vi.fn(async () => 'production' as const),
|
|
13
|
+
getInstallationTimeAsync: vi.fn(async () => 1_563_473_306_121),
|
|
14
|
+
getLastUpdateTimeAsync: vi.fn(async () => 1_563_484_816_887),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const fakePlatform = { OS: 'android' as 'ios' | 'android' };
|
|
18
|
+
|
|
19
|
+
// The real ExpoApplication native module only exists on device — resolving it via
|
|
20
|
+
// requireNativeModule() at import time would throw in this headless test run, so the
|
|
21
|
+
// module-lookup file is faked in place of expo-modules-core's runtime resolution, the same
|
|
22
|
+
// pattern packages/local-auth/src/core/local-authentication.test.ts uses.
|
|
23
|
+
vi.mock('./native-module', () => ({
|
|
24
|
+
expoApplication: FAKE_NATIVE_APPLICATION,
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
// expo-modules-core's real entry transitively imports 'react-native' for Platform/
|
|
28
|
+
// TurboModuleRegistry, whose Flow-typed source Vitest's Oxc transform can't parse — same fake
|
|
29
|
+
// packages/local-auth/src/core/local-authentication.test.ts uses.
|
|
30
|
+
vi.mock('expo-modules-core', () => ({
|
|
31
|
+
Platform: fakePlatform,
|
|
32
|
+
UnavailabilityError: class UnavailabilityError extends Error {
|
|
33
|
+
constructor(moduleName: string, propertyName: string) {
|
|
34
|
+
super(`${propertyName} is not available on ${moduleName}`);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
nativeApplicationVersion,
|
|
41
|
+
nativeBuildVersion,
|
|
42
|
+
applicationName,
|
|
43
|
+
applicationId,
|
|
44
|
+
getAndroidId,
|
|
45
|
+
getInstallReferrerAsync,
|
|
46
|
+
getIosIdForVendorAsync,
|
|
47
|
+
getIosApplicationReleaseTypeAsync,
|
|
48
|
+
getIosPushNotificationServiceEnvironmentAsync,
|
|
49
|
+
getInstallationTimeAsync,
|
|
50
|
+
getLastUpdateTimeAsync,
|
|
51
|
+
} = await import('./application');
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
fakePlatform.OS = 'android';
|
|
55
|
+
vi.clearAllMocks();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('constants', () => {
|
|
59
|
+
it('resolves eagerly from the native module', () => {
|
|
60
|
+
expect(nativeApplicationVersion).toBe('2.11.0');
|
|
61
|
+
expect(nativeBuildVersion).toBe('114');
|
|
62
|
+
expect(applicationName).toBe('Canary');
|
|
63
|
+
expect(applicationId).toBe('com.symbiote.canary');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('getAndroidId', () => {
|
|
68
|
+
it('returns the native androidId on android', () => {
|
|
69
|
+
expect(getAndroidId()).toBe('dd96dec43fb81c97');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('throws an UnavailabilityError-shaped error on a non-android platform', () => {
|
|
73
|
+
fakePlatform.OS = 'ios';
|
|
74
|
+
expect(() => getAndroidId()).toThrow('androidId is not available on expo-application');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('getInstallReferrerAsync', () => {
|
|
79
|
+
it('delegates to the native module', async () => {
|
|
80
|
+
await expect(getInstallReferrerAsync()).resolves.toBe(
|
|
81
|
+
'utm_source=google-play&utm_medium=organic',
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
|
|
86
|
+
const { getInstallReferrerAsync: native } = FAKE_NATIVE_APPLICATION;
|
|
87
|
+
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
88
|
+
FAKE_NATIVE_APPLICATION.getInstallReferrerAsync = undefined;
|
|
89
|
+
|
|
90
|
+
await expect(getInstallReferrerAsync()).rejects.toThrow(
|
|
91
|
+
'getInstallReferrerAsync is not available on expo-application',
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
FAKE_NATIVE_APPLICATION.getInstallReferrerAsync = native;
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('getIosIdForVendorAsync', () => {
|
|
99
|
+
it('delegates to the native module', async () => {
|
|
100
|
+
await expect(getIosIdForVendorAsync()).resolves.toBe('68753A44-4D6F-1226-9C60-0050E4C00067');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('getIosApplicationReleaseTypeAsync', () => {
|
|
105
|
+
it('delegates to the native module', async () => {
|
|
106
|
+
await expect(getIosApplicationReleaseTypeAsync()).resolves.toBe(5);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
|
|
110
|
+
const { getApplicationReleaseTypeAsync: native } = FAKE_NATIVE_APPLICATION;
|
|
111
|
+
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
112
|
+
FAKE_NATIVE_APPLICATION.getApplicationReleaseTypeAsync = undefined;
|
|
113
|
+
|
|
114
|
+
await expect(getIosApplicationReleaseTypeAsync()).rejects.toThrow(
|
|
115
|
+
'getApplicationReleaseTypeAsync is not available on expo-application',
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
FAKE_NATIVE_APPLICATION.getApplicationReleaseTypeAsync = native;
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('getIosPushNotificationServiceEnvironmentAsync', () => {
|
|
123
|
+
it('delegates to the native module', async () => {
|
|
124
|
+
await expect(getIosPushNotificationServiceEnvironmentAsync()).resolves.toBe('production');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('getInstallationTimeAsync', () => {
|
|
129
|
+
it('wraps the native epoch-ms number into a Date', async () => {
|
|
130
|
+
await expect(getInstallationTimeAsync()).resolves.toEqual(new Date(1_563_473_306_121));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('getLastUpdateTimeAsync', () => {
|
|
135
|
+
it('wraps the native epoch-ms number into a Date', async () => {
|
|
136
|
+
await expect(getLastUpdateTimeAsync()).resolves.toEqual(new Date(1_563_484_816_887));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
|
|
140
|
+
const { getLastUpdateTimeAsync: native } = FAKE_NATIVE_APPLICATION;
|
|
141
|
+
// @ts-expect-error -- simulating iOS, where getLastUpdateTimeAsync has no native implementation
|
|
142
|
+
FAKE_NATIVE_APPLICATION.getLastUpdateTimeAsync = undefined;
|
|
143
|
+
|
|
144
|
+
await expect(getLastUpdateTimeAsync()).rejects.toThrow(
|
|
145
|
+
'getLastUpdateTimeAsync is not available on expo-application',
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
FAKE_NATIVE_APPLICATION.getLastUpdateTimeAsync = native;
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
|
|
3
|
+
import { expoApplication } from './native-module';
|
|
4
|
+
import type { ApplicationReleaseType, PushNotificationServiceEnvironment } from './types';
|
|
5
|
+
|
|
6
|
+
const NATIVE_MODULE_NAME = 'expo-application';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The human-readable version of the native application that may be displayed in the app store.
|
|
10
|
+
* On Android, this is the version name set by `version` in the app config; on iOS, the
|
|
11
|
+
* `Info.plist` value for `CFBundleShortVersionString`.
|
|
12
|
+
* @example `"2.11.0"`
|
|
13
|
+
*/
|
|
14
|
+
export const nativeApplicationVersion: string | null =
|
|
15
|
+
expoApplication.nativeApplicationVersion ?? null;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The internal build version of the native application that the app stores may use to
|
|
19
|
+
* distinguish between different binaries. On Android, this is `android.versionCode`; on iOS,
|
|
20
|
+
* the `Info.plist` value for `CFBundleVersion` (`ios.buildNumber` in the app config).
|
|
21
|
+
* @example `"114"`
|
|
22
|
+
*/
|
|
23
|
+
export const nativeBuildVersion: string | null = expoApplication.nativeBuildVersion ?? null;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The human-readable name of the application, displayed with the app's icon on the device's
|
|
27
|
+
* home screen.
|
|
28
|
+
* @example `"Expo"`, `"Yelp"`, `"Instagram"`
|
|
29
|
+
*/
|
|
30
|
+
export const applicationName: string | null = expoApplication.applicationName ?? null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The ID of the application. On Android, this is the application ID. On iOS, this is the
|
|
34
|
+
* bundle ID.
|
|
35
|
+
* @example `"com.cocoacasts.scribbles"`, `"com.apple.Pages"`
|
|
36
|
+
*/
|
|
37
|
+
export const applicationId: string | null = expoApplication.applicationId ?? null;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Gets the value of `Settings.Secure.ANDROID_ID` — a hexadecimal string unique to each
|
|
41
|
+
* combination of app-signing key, user, and device. The value may change if a factory reset is
|
|
42
|
+
* performed on the device or if an APK signing key changes.
|
|
43
|
+
* @example `Application.getAndroidId(); // "dd96dec43fb81c97"`
|
|
44
|
+
* @platform android
|
|
45
|
+
*/
|
|
46
|
+
export function getAndroidId(): string {
|
|
47
|
+
if (Platform.OS !== 'android') {
|
|
48
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'androidId');
|
|
49
|
+
}
|
|
50
|
+
if (!expoApplication.androidId) {
|
|
51
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'androidId');
|
|
52
|
+
}
|
|
53
|
+
return expoApplication.androidId;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Gets the referrer URL of the installed app with the Install Referrer API from the Google Play
|
|
58
|
+
* Store. In practice, the referrer URL may not be a complete, absolute URL.
|
|
59
|
+
* @example `await Application.getInstallReferrerAsync(); // "utm_source=google-play&utm_medium=organic"`
|
|
60
|
+
* @platform android
|
|
61
|
+
*/
|
|
62
|
+
export async function getInstallReferrerAsync(): Promise<string> {
|
|
63
|
+
if (!expoApplication.getInstallReferrerAsync) {
|
|
64
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getInstallReferrerAsync');
|
|
65
|
+
}
|
|
66
|
+
return expoApplication.getInstallReferrerAsync();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the iOS "identifier for vendor" (IDFV) — a string ID that uniquely identifies a device to
|
|
71
|
+
* the app's vendor. May resolve `null`, in which case wait and call again later (this can happen
|
|
72
|
+
* when the device was restarted before the user unlocked it). The OS changes the vendor
|
|
73
|
+
* identifier once every app from the current vendor has been uninstalled.
|
|
74
|
+
* @example `await Application.getIosIdForVendorAsync(); // "68753A44-4D6F-1226-9C60-0050E4C00067"`
|
|
75
|
+
* @platform ios
|
|
76
|
+
*/
|
|
77
|
+
export async function getIosIdForVendorAsync(): Promise<string | null> {
|
|
78
|
+
if (!expoApplication.getIosIdForVendorAsync) {
|
|
79
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getIosIdForVendorAsync');
|
|
80
|
+
}
|
|
81
|
+
return expoApplication.getIosIdForVendorAsync();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Gets the iOS application release type.
|
|
86
|
+
* @platform ios
|
|
87
|
+
*/
|
|
88
|
+
export async function getIosApplicationReleaseTypeAsync(): Promise<ApplicationReleaseType> {
|
|
89
|
+
if (!expoApplication.getApplicationReleaseTypeAsync) {
|
|
90
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getApplicationReleaseTypeAsync');
|
|
91
|
+
}
|
|
92
|
+
return expoApplication.getApplicationReleaseTypeAsync();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Gets the current Apple Push Notification (APN) service environment.
|
|
97
|
+
* @return Either `'development'` or `'production'`, or `null` on the simulator (which does not
|
|
98
|
+
* support registering with APNs).
|
|
99
|
+
* @platform ios
|
|
100
|
+
*/
|
|
101
|
+
export async function getIosPushNotificationServiceEnvironmentAsync(): Promise<PushNotificationServiceEnvironment> {
|
|
102
|
+
if (!expoApplication.getPushNotificationServiceEnvironmentAsync) {
|
|
103
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getPushNotificationServiceEnvironmentAsync');
|
|
104
|
+
}
|
|
105
|
+
return expoApplication.getPushNotificationServiceEnvironmentAsync();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Gets the time the app was installed onto the device, not counting subsequent updates. If the
|
|
110
|
+
* app is uninstalled and reinstalled, this returns the time of the reinstall.
|
|
111
|
+
* - Android: `PackageInfo.firstInstallTime`.
|
|
112
|
+
* - iOS: the `NSFileCreationDate` of the app's document root directory.
|
|
113
|
+
* @example `await Application.getInstallationTimeAsync(); // 2019-07-18T18:08:26.121Z`
|
|
114
|
+
*/
|
|
115
|
+
export async function getInstallationTimeAsync(): Promise<Date> {
|
|
116
|
+
if (!expoApplication.getInstallationTimeAsync) {
|
|
117
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getInstallationTimeAsync');
|
|
118
|
+
}
|
|
119
|
+
const installationTime = await expoApplication.getInstallationTimeAsync();
|
|
120
|
+
return new Date(installationTime);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Gets the last time the app was updated from the Google Play Store.
|
|
125
|
+
* @example `await Application.getLastUpdateTimeAsync(); // 2019-07-18T21:20:16.887Z`
|
|
126
|
+
* @platform android
|
|
127
|
+
*/
|
|
128
|
+
export async function getLastUpdateTimeAsync(): Promise<Date> {
|
|
129
|
+
if (!expoApplication.getLastUpdateTimeAsync) {
|
|
130
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getLastUpdateTimeAsync');
|
|
131
|
+
}
|
|
132
|
+
const lastUpdateTime = await expoApplication.getLastUpdateTimeAsync();
|
|
133
|
+
return new Date(lastUpdateTime);
|
|
134
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export {
|
|
2
|
+
nativeApplicationVersion,
|
|
3
|
+
nativeBuildVersion,
|
|
4
|
+
applicationName,
|
|
5
|
+
applicationId,
|
|
6
|
+
getAndroidId,
|
|
7
|
+
getInstallReferrerAsync,
|
|
8
|
+
getIosIdForVendorAsync,
|
|
9
|
+
getIosApplicationReleaseTypeAsync,
|
|
10
|
+
getIosPushNotificationServiceEnvironmentAsync,
|
|
11
|
+
getInstallationTimeAsync,
|
|
12
|
+
getLastUpdateTimeAsync,
|
|
13
|
+
} from './application';
|
|
14
|
+
export { ApplicationReleaseType, type PushNotificationServiceEnvironment } from './types';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
import type { ApplicationReleaseType, PushNotificationServiceEnvironment } from './types';
|
|
3
|
+
|
|
4
|
+
const EXPO_APPLICATION_MODULE_NAME = 'ExpoApplication';
|
|
5
|
+
|
|
6
|
+
// Every method is optional — each call site checks for its presence before calling through and
|
|
7
|
+
// throws an UnavailabilityError itself, matching upstream's own per-platform capability checks
|
|
8
|
+
// rather than assuming the native module implements the whole surface. Same convention as
|
|
9
|
+
// packages/local-auth/src/core/native-module.ts.
|
|
10
|
+
export type INativeApplicationModule = {
|
|
11
|
+
nativeApplicationVersion?: string | null;
|
|
12
|
+
nativeBuildVersion?: string | null;
|
|
13
|
+
applicationName?: string | null;
|
|
14
|
+
applicationId?: string | null;
|
|
15
|
+
androidId?: string;
|
|
16
|
+
getInstallReferrerAsync?(): Promise<string>;
|
|
17
|
+
getIosIdForVendorAsync?(): Promise<string | null>;
|
|
18
|
+
getApplicationReleaseTypeAsync?(): Promise<ApplicationReleaseType>;
|
|
19
|
+
getPushNotificationServiceEnvironmentAsync?(): Promise<PushNotificationServiceEnvironment>;
|
|
20
|
+
getInstallationTimeAsync?(): Promise<number>;
|
|
21
|
+
getLastUpdateTimeAsync?(): Promise<number>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const expoApplication = requireNativeModule<INativeApplicationModule>(
|
|
25
|
+
EXPO_APPLICATION_MODULE_NAME,
|
|
26
|
+
);
|