@symbiote-native/application 0.0.1 → 0.2.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/README.md CHANGED
@@ -159,9 +159,10 @@ export class ApplicationScreen {
159
159
  ```
160
160
 
161
161
  There's no per-instance service to `inject()` in the Angular case — every function is a plain
162
- free function off the core package, called straight from the constructor. Not yet demoed in any
163
- of the `examples/expo-*` canary apps — the code above is realistic, hand-written usage of the
164
- real API, not trimmed from an existing screen.
162
+ free function off the core package, called straight from the constructor. All three examples
163
+ mirror the real canary demo screens — `examples/expo-react/screens/ApplicationScreen.tsx`,
164
+ `examples/expo-vue-sfc/screens/ApplicationScreen.vue`, `examples/expo-vue-tsx/screens/ApplicationScreen.tsx`,
165
+ `examples/expo-angular/src/screens/ApplicationScreen.ts`.
165
166
 
166
167
  ## API
167
168
 
@@ -218,6 +219,5 @@ the real `requireNativeModule` resolution (`src/core/application.test.ts`, `vite
218
219
  [README](../../README.md) for the project's testing model).
219
220
 
220
221
  Native autolinking wiring is shared with `@symbiote-native/local-auth` and every other
221
- `expo-modules-core` package in this repo's `examples/expo-*` canaries — this package itself isn't
222
- yet demoed in any of them (no `ApplicationScreen`/equivalent exists yet), so the "Use it" section
223
- above is realistic example code, not a trimmed-down copy of a running demo.
222
+ `expo-modules-core` package in this repo's `examples/expo-*` canaries, where this package is
223
+ demoed by the `ApplicationScreen` of each app.
@@ -1,4 +1,4 @@
1
1
  // @symbiote-native/application/angular: the Angular entry over the framework-agnostic core.
2
2
  // Same reasoning as the React/Vue entries — no per-instance state or event stream to wrap in a
3
3
  // service, so this is a plain re-export.
4
- export * from '../core';
4
+ export * from '../core/index.js';
@@ -1,5 +1,5 @@
1
1
  import { Platform, UnavailabilityError } from 'expo-modules-core';
2
- import { expoApplication } from './native-module';
2
+ import { expoApplication } from './native-module.js';
3
3
  const NATIVE_MODULE_NAME = 'expo-application';
4
4
  /**
5
5
  * The human-readable version of the native application that may be displayed in the app store.
@@ -1,2 +1,2 @@
1
- export { nativeApplicationVersion, nativeBuildVersion, applicationName, applicationId, getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync, getIosApplicationReleaseTypeAsync, getIosPushNotificationServiceEnvironmentAsync, getInstallationTimeAsync, getLastUpdateTimeAsync, } from './application';
2
- export { ApplicationReleaseType } from './types';
1
+ export { nativeApplicationVersion, nativeBuildVersion, applicationName, applicationId, getAndroidId, getInstallReferrerAsync, getIosIdForVendorAsync, getIosApplicationReleaseTypeAsync, getIosPushNotificationServiceEnvironmentAsync, getInstallationTimeAsync, getLastUpdateTimeAsync, } from './application.js';
2
+ export { ApplicationReleaseType } from './types.js';
@@ -2,4 +2,4 @@
2
2
  // Upstream ships plain constants and one-shot async functions, no per-instance state and no
3
3
  // event stream — there is nothing for a hook to wrap, so this is a plain re-export, mirroring
4
4
  // packages/local-auth/src/react/index.ts.
5
- export * from '../core';
5
+ export * from '../core/index.js';
@@ -0,0 +1 @@
1
+ export * from '../core';
@@ -0,0 +1,6 @@
1
+ // @symbiote-native/application/svelte: the Svelte entry over the framework-agnostic core.
2
+ // Upstream ships plain constants and one-shot async functions, no per-instance state and no
3
+ // event stream — there is nothing for a rune to wrap, so this is a plain re-export. Svelte's
4
+ // lifecycle bucket is `runes/` (adapters/svelte/src/runes — never React's `hooks` or Vue's
5
+ // `composables`), and this package has none to fill.
6
+ export * from '../core/index.js';
@@ -1,4 +1,4 @@
1
1
  // @symbiote-native/application/vue: the Vue entry over the framework-agnostic core. Same
2
2
  // reasoning as the React entry — no per-instance state or event stream to wire onto Vue's
3
3
  // reactivity, so this is a plain re-export.
4
- export * from '../core';
4
+ export * from '../core/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/application",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
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
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,6 +30,10 @@
30
30
  "types": "./build/react/index.d.ts",
31
31
  "default": "./build/react/index.js"
32
32
  },
33
+ "./svelte": {
34
+ "types": "./build/svelte/index.d.ts",
35
+ "default": "./build/svelte/index.js"
36
+ },
33
37
  "./angular": {
34
38
  "types": "./build-ngc/angular/index.d.ts",
35
39
  "react-native": "./build-ngc/angular/index.js",
@@ -40,7 +44,10 @@
40
44
  "src",
41
45
  "build",
42
46
  "build-ngc",
43
- "native-link.json"
47
+ "native-link.json",
48
+ "!src/**/*.test.*",
49
+ "!src/**/*.spec.*",
50
+ "!src/**/*.detox.*"
44
51
  ],
45
52
  "publishConfig": {
46
53
  "access": "public"
@@ -50,15 +57,17 @@
50
57
  "expo-modules-core": "57.0.5"
51
58
  },
52
59
  "peerDependencies": {
60
+ "@symbiote-native/angular": ">=0.6.2",
53
61
  "@symbiote-native/engine": ">=0.1.7",
62
+ "@symbiote-native/react": ">=0.2.8",
63
+ "@symbiote-native/svelte": ">=0.1.0",
64
+ "@symbiote-native/vue": ">=0.3.8",
54
65
  "@angular/core": ">=20",
55
66
  "@vue/runtime-core": "^3.5.13",
56
67
  "react": ">=19.0.0",
57
68
  "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"
69
+ "svelte": ">=5.56.0",
70
+ "vue": ">=3.5.0"
62
71
  },
63
72
  "peerDependenciesMeta": {
64
73
  "@symbiote-native/angular": {
@@ -67,6 +76,9 @@
67
76
  "@symbiote-native/react": {
68
77
  "optional": true
69
78
  },
79
+ "@symbiote-native/svelte": {
80
+ "optional": true
81
+ },
70
82
  "@symbiote-native/vue": {
71
83
  "optional": true
72
84
  },
@@ -79,24 +91,29 @@
79
91
  "react": {
80
92
  "optional": true
81
93
  },
94
+ "svelte": {
95
+ "optional": true
96
+ },
82
97
  "vue": {
83
98
  "optional": true
84
99
  }
85
100
  },
86
101
  "devDependencies": {
87
- "@angular/compiler": "^22",
88
- "@angular/compiler-cli": "^22",
89
- "@angular/core": "^22",
102
+ "@angular/compiler": "~22.0.8",
103
+ "@angular/compiler-cli": "~22.0.8",
104
+ "@angular/core": "~22.0.8",
90
105
  "@types/node": "^26.0.0",
91
106
  "@types/react": "^19.2.0",
92
107
  "@vue/runtime-core": "^3.5.13",
93
108
  "react": "19.2.3",
109
+ "svelte": "^5.56.0",
94
110
  "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",
111
+ "@symbiote-native/angular": "0.7.0",
112
+ "@symbiote-native/engine": "0.2.0",
113
+ "@symbiote-native/react": "0.3.0",
114
+ "@symbiote-native/svelte": "0.2.0",
98
115
  "@symbiote-native/test-utils": "0.1.6",
99
- "@symbiote-native/vue": "0.3.8"
116
+ "@symbiote-native/vue": "0.4.0"
100
117
  },
101
118
  "scripts": {
102
119
  "typecheck": "tsc --build",
@@ -0,0 +1,6 @@
1
+ // @symbiote-native/application/svelte: the Svelte entry over the framework-agnostic core.
2
+ // Upstream ships plain constants and one-shot async functions, no per-instance state and no
3
+ // event stream — there is nothing for a rune to wrap, so this is a plain re-export. Svelte's
4
+ // lifecycle bucket is `runes/` (adapters/svelte/src/runes — never React's `hooks` or Vue's
5
+ // `composables`), and this package has none to fill.
6
+ export * from '../core';
@@ -1,150 +0,0 @@
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
- });