@symbiote-native/tracking-transparency 3.0.1 → 3.1.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 +78 -73
- package/build/angular/index.d.ts +1 -1
- package/build/angular/index.js +2 -3
- package/build/angular/tracking-permissions.service.d.ts +5 -0
- package/build/angular/{services/permissions.service/index.js → tracking-permissions.service.js} +13 -48
- package/build/core/tracking-permission-api.d.ts +5 -0
- package/build/core/tracking-permission-api.js +7 -0
- package/build/react/index.d.ts +1 -1
- package/build/react/index.js +2 -5
- package/build/react/use-tracking-permissions.d.ts +8 -0
- package/build/react/use-tracking-permissions.js +4 -0
- package/build/solid/index.d.ts +1 -1
- package/build/solid/index.js +2 -6
- package/build/solid/use-tracking-permissions.d.ts +9 -0
- package/build/solid/use-tracking-permissions.js +4 -0
- package/build/svelte/index.d.ts +1 -1
- package/build/svelte/index.js +2 -5
- package/build/svelte/use-tracking-permissions.svelte.d.ts +8 -0
- package/build/svelte/use-tracking-permissions.svelte.js +4 -0
- package/build/vue/index.d.ts +1 -1
- package/build/vue/index.js +2 -5
- package/build/vue/use-tracking-permissions.d.ts +9 -0
- package/build/vue/use-tracking-permissions.js +4 -0
- package/build-ngc/angular/index.d.ts +1 -1
- package/build-ngc/angular/index.js +2 -3
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/tracking-permissions.service.d.ts +8 -0
- package/build-ngc/angular/tracking-permissions.service.js +17 -0
- package/build-ngc/angular/tracking-permissions.service.js.map +1 -0
- package/build-ngc/core/tracking-permission-api.d.ts +5 -0
- package/build-ngc/core/tracking-permission-api.js +8 -0
- package/build-ngc/core/tracking-permission-api.js.map +1 -0
- package/package.json +15 -15
- package/src/angular/index.ts +2 -3
- package/src/angular/tracking-permissions.service.ts +16 -0
- package/src/core/tracking-permission-api.ts +12 -0
- package/src/react/index.ts +5 -6
- package/src/react/use-tracking-permissions.ts +16 -0
- package/src/solid/index.ts +5 -7
- package/src/solid/use-tracking-permissions.ts +17 -0
- package/src/svelte/index.ts +5 -6
- package/src/svelte/svelte-compile.test-helper.ts +6 -0
- package/src/svelte/use-tracking-permissions.svelte.ts +16 -0
- package/src/vue/index.ts +5 -6
- package/src/vue/use-tracking-permissions.ts +17 -0
- package/build/angular/services/permissions.service/index.d.ts +0 -12
- package/build/react/hooks/use-permissions/index.d.ts +0 -7
- package/build/react/hooks/use-permissions/index.js +0 -43
- package/build/solid/primitives/create-permissions.d.ts +0 -8
- package/build/solid/primitives/create-permissions.js +0 -41
- package/build/svelte/runes/use-permissions.svelte.d.ts +0 -7
- package/build/svelte/runes/use-permissions.svelte.js +0 -49
- package/build/vue/composables/use-permissions/index.d.ts +0 -8
- package/build/vue/composables/use-permissions/index.js +0 -33
- package/build-ngc/angular/services/permissions.service/index.d.ts +0 -15
- package/build-ngc/angular/services/permissions.service/index.js +0 -55
- package/build-ngc/angular/services/permissions.service/index.js.map +0 -1
- package/src/angular/services/permissions.service/index.ts +0 -57
- package/src/react/hooks/use-permissions/index.ts +0 -57
- package/src/solid/primitives/create-permissions.ts +0 -56
- package/src/svelte/runes/use-permissions.svelte.ts +0 -63
- package/src/vue/composables/use-permissions/index.ts +0 -47
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# @symbiote-native/tracking-transparency
|
|
2
2
|
|
|
3
3
|
A wrapper package for [SymbioteNative](../../README.md) that makes
|
|
4
|
-
[`expo-tracking-transparency`](https://github.com/expo/expo/tree/main/packages/expo-tracking-transparency)
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
[`expo-tracking-transparency`](https://github.com/expo/expo/tree/main/packages/expo-tracking-transparency):
|
|
5
|
+
the iOS App Tracking Transparency prompt, permission get/request, and the advertising-ID getter,
|
|
6
|
+
usable from **every** adapter, React, Vue, Svelte, Solid, and Angular, not just React. Like
|
|
7
7
|
[`@symbiote-native/brightness`](../brightness), this package's surface is mostly stateless free
|
|
8
8
|
async functions; only the permission surface gets its own per-adapter lifecycle wrapper,
|
|
9
|
-
mirroring upstream's own `
|
|
9
|
+
mirroring upstream's own `useTrackingPermissions`. Built the same way as
|
|
10
10
|
[`@symbiote-native/local-auth`](../local-auth), [`@symbiote-native/battery`](../battery), and
|
|
11
|
-
[`@symbiote-native/brightness`](../brightness)
|
|
11
|
+
[`@symbiote-native/brightness`](../brightness) - an `expo-modules-core`-based wrapper (see the
|
|
12
12
|
`symbiote-expo-native-module` project skill for the full mechanism: why `expo-modules-core` is
|
|
13
13
|
depended on directly and never the `expo` meta-package, why the upstream JS is hand-ported into
|
|
14
14
|
`core/` rather than imported, and how autolinking picks up the native module).
|
|
@@ -32,16 +32,16 @@ npx @symbiote-native/cli add --tracking-transparency
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Either way: installs `@symbiote-native/tracking-transparency` and wires the native autolinking
|
|
35
|
-
automatically
|
|
35
|
+
automatically - see [`@symbiote-native/cli`](../cli).
|
|
36
36
|
|
|
37
37
|
<details>
|
|
38
|
-
<summary>Manual install (no CLI
|
|
38
|
+
<summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
npm install @symbiote-native/tracking-transparency
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`expo-tracking-transparency` and `expo-modules-core` come along as regular, pinned dependencies
|
|
44
|
+
`expo-tracking-transparency` and `expo-modules-core` come along as regular, pinned dependencies:
|
|
45
45
|
never install either yourself, and never add the `expo` meta-package to this project (it bundles
|
|
46
46
|
its own Metro/Babel pipeline that conflicts with this project's own).
|
|
47
47
|
|
|
@@ -49,21 +49,21 @@ its own Metro/Babel pipeline that conflicts with this project's own).
|
|
|
49
49
|
|
|
50
50
|
Unlike a plain RN native module, `expo-tracking-transparency`'s native code is discovered by
|
|
51
51
|
`expo-modules-autolinking`, not the `react-native.config.cjs`/podspec mechanism other wrappers in
|
|
52
|
-
this repo use
|
|
52
|
+
this repo use - this needs wiring into the native host app **once**, covering this package and
|
|
53
53
|
every other `expo-modules-core` package with zero further changes:
|
|
54
54
|
|
|
55
55
|
| Platform | Touches |
|
|
56
56
|
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
-
| iOS | `ios/Podfile`
|
|
58
|
-
| iOS | `AppDelegate.swift`
|
|
59
|
-
| iOS | `Info.plist`
|
|
60
|
-
| Android | `settings.gradle` / `app/build.gradle`
|
|
61
|
-
| Android | `MainApplication.kt`
|
|
62
|
-
|
|
63
|
-
Full mechanics
|
|
64
|
-
peer-dependency exclusion list
|
|
57
|
+
| iOS | `ios/Podfile` - add `use_expo_modules!` |
|
|
58
|
+
| iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
|
|
59
|
+
| iOS | `Info.plist` - `NSUserTrackingUsageDescription`, required to show the ATT prompt |
|
|
60
|
+
| Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
|
|
61
|
+
| Android | `MainApplication.kt` - Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
|
|
62
|
+
|
|
63
|
+
Full mechanics - the Podfile pieces that normally ship inside the `expo` package, the `expo`
|
|
64
|
+
peer-dependency exclusion list - live in the `symbiote-expo-native-module` skill. The Android
|
|
65
65
|
native module also pulls in `com.google.android.gms:play-services-ads-identifier:18.0.1`
|
|
66
|
-
transitively via `expo-tracking-transparency`'s own `android/build.gradle`
|
|
66
|
+
transitively via `expo-tracking-transparency`'s own `android/build.gradle` - automatic once the
|
|
67
67
|
module project is included, no extra wiring needed on our side.
|
|
68
68
|
|
|
69
69
|
</details>
|
|
@@ -74,32 +74,31 @@ module project is included, no extra wiring needed on our side.
|
|
|
74
74
|
src/core/ getAdvertisingId, get/requestTrackingPermissionsAsync, isAvailable;
|
|
75
75
|
native-module.ts resolves ExpoTrackingTransparency through
|
|
76
76
|
expo-modules-core's requireNativeModule.
|
|
77
|
-
src/react/
|
|
78
|
-
src/vue/
|
|
79
|
-
src/svelte/
|
|
80
|
-
src/solid/
|
|
81
|
-
|
|
82
|
-
src/angular/services/ @symbiote-native/tracking-transparency/angular — PermissionsService
|
|
77
|
+
src/react/ @symbiote-native/tracking-transparency/react: useTrackingPermissions
|
|
78
|
+
src/vue/ @symbiote-native/tracking-transparency/vue: useTrackingPermissions
|
|
79
|
+
src/svelte/ @symbiote-native/tracking-transparency/svelte: useTrackingPermissions
|
|
80
|
+
src/solid/ @symbiote-native/tracking-transparency/solid: useTrackingPermissions
|
|
81
|
+
src/angular/ @symbiote-native/tracking-transparency/angular: TrackingPermissionsService
|
|
83
82
|
```
|
|
84
83
|
|
|
85
|
-
Each adapter
|
|
86
|
-
`
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
Each adapter binds the same `getTrackingPermissionsAsync`/`requestTrackingPermissionsAsync` pair
|
|
85
|
+
(`core/tracking-permission-api.ts`) to the shared `createPermissionHook` of its adapter, or to
|
|
86
|
+
`PermissionsServiceBase` on Angular. `getAdvertisingId`/`isAvailable` are stateless free-function
|
|
87
|
+
re-exports, written once in `core/` and shared verbatim by every adapter.
|
|
89
88
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
`useTrackingPermissions` takes upstream's `{ get, request }` options: it fetches on mount by
|
|
90
|
+
default, `{ request: true }` asks instead, `{ get: false }` does nothing until called. Unlike the
|
|
91
|
+
former `usePermissions`, the hooks carry no `error` slot; Angular's service keeps `error`.
|
|
93
92
|
|
|
94
93
|
## Use it
|
|
95
94
|
|
|
96
95
|
```tsx
|
|
97
96
|
// React
|
|
98
|
-
import {
|
|
97
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/react';
|
|
99
98
|
import { getAdvertisingId } from '@symbiote-native/tracking-transparency';
|
|
100
99
|
|
|
101
100
|
function TrackingScreen() {
|
|
102
|
-
const [permissionStatus, requestPermission] =
|
|
101
|
+
const [permissionStatus, requestPermission] = useTrackingPermissions();
|
|
103
102
|
|
|
104
103
|
return (
|
|
105
104
|
<view>
|
|
@@ -118,11 +117,10 @@ function TrackingScreen() {
|
|
|
118
117
|
```vue
|
|
119
118
|
<!-- Vue -->
|
|
120
119
|
<script setup lang="ts">
|
|
121
|
-
import {
|
|
120
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/vue';
|
|
122
121
|
import { getAdvertisingId } from '@symbiote-native/tracking-transparency';
|
|
123
122
|
|
|
124
|
-
const
|
|
125
|
-
usePermissions();
|
|
123
|
+
const [permissionStatus, requestPermission] = useTrackingPermissions();
|
|
126
124
|
</script>
|
|
127
125
|
|
|
128
126
|
<template>
|
|
@@ -142,7 +140,7 @@ const { status: permissionStatus, request: requestPermission } =
|
|
|
142
140
|
// Angular
|
|
143
141
|
import { Component, inject } from '@angular/core';
|
|
144
142
|
import {
|
|
145
|
-
|
|
143
|
+
TrackingPermissionsService,
|
|
146
144
|
getAdvertisingId,
|
|
147
145
|
} from '@symbiote-native/tracking-transparency/angular';
|
|
148
146
|
|
|
@@ -162,7 +160,7 @@ import {
|
|
|
162
160
|
`,
|
|
163
161
|
})
|
|
164
162
|
export class TrackingScreen {
|
|
165
|
-
protected readonly permissionsService = inject(
|
|
163
|
+
protected readonly permissionsService = inject(TrackingPermissionsService);
|
|
166
164
|
readonly permissionStatus = this.permissionsService.connect();
|
|
167
165
|
|
|
168
166
|
logAdvertisingId(): void {
|
|
@@ -172,20 +170,20 @@ export class TrackingScreen {
|
|
|
172
170
|
```
|
|
173
171
|
|
|
174
172
|
```svelte
|
|
175
|
-
<!-- Svelte
|
|
173
|
+
<!-- Svelte - the rune hands back a boxed object whose `status` is a getter; destructuring it
|
|
176
174
|
would freeze the value at its initial null, since Svelte 5 reactivity is lexically scoped. -->
|
|
177
175
|
<script lang="ts">
|
|
178
176
|
import {
|
|
179
177
|
getAdvertisingId,
|
|
180
|
-
|
|
178
|
+
useTrackingPermissions,
|
|
181
179
|
} from '@symbiote-native/tracking-transparency/svelte';
|
|
182
180
|
|
|
183
|
-
const permissions =
|
|
181
|
+
const permissions = useTrackingPermissions();
|
|
184
182
|
</script>
|
|
185
183
|
|
|
186
184
|
<view>
|
|
187
185
|
<text>{permissions.status?.status ?? 'checking…'}</text>
|
|
188
|
-
<pressable onPress={() => permissions.
|
|
186
|
+
<pressable onPress={() => permissions.requestPermission()}>
|
|
189
187
|
<text>Request tracking permission</text>
|
|
190
188
|
</pressable>
|
|
191
189
|
<pressable onPress={() => console.log(getAdvertisingId())}>
|
|
@@ -195,13 +193,12 @@ export class TrackingScreen {
|
|
|
195
193
|
```
|
|
196
194
|
|
|
197
195
|
```tsx
|
|
198
|
-
// Solid
|
|
199
|
-
import {
|
|
196
|
+
// Solid - the accessors are CALLED; a Solid component body runs once, so a snapshot would freeze.
|
|
197
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/solid';
|
|
200
198
|
import { getAdvertisingId } from '@symbiote-native/tracking-transparency';
|
|
201
199
|
|
|
202
200
|
function TrackingScreen() {
|
|
203
|
-
const
|
|
204
|
-
createPermissions();
|
|
201
|
+
const [permissionStatus, requestPermission] = useTrackingPermissions();
|
|
205
202
|
|
|
206
203
|
return (
|
|
207
204
|
<view>
|
|
@@ -217,7 +214,7 @@ function TrackingScreen() {
|
|
|
217
214
|
}
|
|
218
215
|
```
|
|
219
216
|
|
|
220
|
-
The examples above mirror the real canary demo screens
|
|
217
|
+
The examples above mirror the real canary demo screens:
|
|
221
218
|
`examples/expo-react/screens/TrackingTransparencyScreen.tsx`,
|
|
222
219
|
`examples/expo-vue-sfc/screens/TrackingTransparencyScreen.vue`,
|
|
223
220
|
`examples/expo-vue-tsx/screens/TrackingTransparencyScreen.tsx`,
|
|
@@ -234,14 +231,14 @@ getAdvertisingId(): string | null
|
|
|
234
231
|
|
|
235
232
|
getTrackingPermissionsAsync(): Promise<PermissionResponse>
|
|
236
233
|
requestTrackingPermissionsAsync(): Promise<PermissionResponse>
|
|
237
|
-
// On Android and web these always resolve granted
|
|
234
|
+
// On Android and web these always resolve granted - there is no tracking-consent concept there.
|
|
238
235
|
// On iOS these drive the real ATT prompt / read its current status.
|
|
239
236
|
|
|
240
237
|
isAvailable(): boolean
|
|
241
238
|
// Whether the native module resolved at all.
|
|
242
239
|
```
|
|
243
240
|
|
|
244
|
-
Plus `PermissionStatus`/`PermissionResponse`/`PermissionExpiration`/`PermissionHookOptions
|
|
241
|
+
Plus `PermissionStatus`/`PermissionResponse`/`PermissionExpiration`/`PermissionHookOptions`:
|
|
245
242
|
re-exported verbatim from `expo-modules-core`, never the `expo` meta-package.
|
|
246
243
|
|
|
247
244
|
```ts
|
|
@@ -252,57 +249,65 @@ import {
|
|
|
252
249
|
|
|
253
250
|
// framework-scoped entry points re-export the same free functions, plus a per-adapter
|
|
254
251
|
// permission wrapper:
|
|
255
|
-
import {
|
|
256
|
-
import {
|
|
257
|
-
import {
|
|
258
|
-
import {
|
|
259
|
-
import {
|
|
252
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/react';
|
|
253
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/vue';
|
|
254
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/svelte';
|
|
255
|
+
import { useTrackingPermissions } from '@symbiote-native/tracking-transparency/solid';
|
|
256
|
+
import { TrackingPermissionsService } from '@symbiote-native/tracking-transparency/angular';
|
|
260
257
|
```
|
|
261
258
|
|
|
262
|
-
`
|
|
263
|
-
`
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
it**, or the value freezes at its initial `null` (Svelte 5 reactivity is lexically scoped to the
|
|
268
|
-
property access):
|
|
259
|
+
`useTrackingPermissions` returns a `[status, request, get]` tuple: plain value (React), `Ref` (Vue),
|
|
260
|
+
`Accessor` (Solid). Angular's `TrackingPermissionsService.connect()` returns a readonly `Signal`.
|
|
261
|
+
**Svelte's rune returns a boxed object whose `status` is a getter - do not destructure it**, or
|
|
262
|
+
the value freezes at its initial `null` (Svelte 5 reactivity is lexically scoped to the property
|
|
263
|
+
access); its actions are `requestPermission()` and `getPermission()`:
|
|
269
264
|
|
|
270
265
|
```ts
|
|
271
266
|
// React
|
|
272
|
-
const [status, request] =
|
|
267
|
+
const [status, request] = useTrackingPermissions();
|
|
273
268
|
|
|
274
269
|
// Vue
|
|
275
|
-
const
|
|
270
|
+
const [status, request] = useTrackingPermissions();
|
|
276
271
|
|
|
277
|
-
// Svelte
|
|
278
|
-
const permissions =
|
|
272
|
+
// Svelte - read permissions.status, never destructure it
|
|
273
|
+
const permissions = useTrackingPermissions();
|
|
279
274
|
permissions.status;
|
|
280
275
|
|
|
281
|
-
// Solid
|
|
282
|
-
const
|
|
276
|
+
// Solid - status is an accessor, called at the read site
|
|
277
|
+
const [status, request] = useTrackingPermissions();
|
|
283
278
|
|
|
284
279
|
// Angular
|
|
285
|
-
readonly status = inject(
|
|
280
|
+
readonly status = inject(TrackingPermissionsService).connect();
|
|
286
281
|
```
|
|
287
282
|
|
|
288
283
|
## Platform notes
|
|
289
284
|
|
|
290
285
|
- **Android and web always report granted.** There is no tracking-consent concept on either
|
|
291
|
-
platform
|
|
286
|
+
platform - `getTrackingPermissionsAsync`/`requestTrackingPermissionsAsync` short-circuit to a
|
|
292
287
|
fixed granted response without ever calling the native module, matching upstream exactly.
|
|
293
|
-
- **`getAdvertisingId` returns `null` on the iOS Simulator, regardless of any settings**
|
|
288
|
+
- **`getAdvertisingId` returns `null` on the iOS Simulator, regardless of any settings** - there is
|
|
294
289
|
no real IDFA to read there. This is expected Apple Simulator behavior, not a bug in this wrapper.
|
|
295
290
|
|
|
291
|
+
## Common questions
|
|
292
|
+
|
|
293
|
+
- **Crash on request.** `NSUserTrackingUsageDescription` is missing from Info.plist.
|
|
294
|
+
- **Dialog never appears.** Request only while the app state is `active`; guard duplicates.
|
|
295
|
+
- **Rejection under Guideline 5.1.2.** Generic text is rejected; state a concrete user benefit.
|
|
296
|
+
|
|
297
|
+
Sources: [Expo docs: TrackingTransparency](https://docs.expo.dev/versions/latest/sdk/tracking-transparency/),
|
|
298
|
+
[expo/expo#13059](https://github.com/expo/expo/issues/13059),
|
|
299
|
+
[Implement App Tracking Transparency with Expo](https://yosukep.medium.com/implement-app-tracking-transparency-with-expo-app-58cf77cb168d).
|
|
300
|
+
|
|
296
301
|
## Test it
|
|
297
302
|
|
|
298
|
-
No Fabric/Descriptor angle at all
|
|
303
|
+
No Fabric/Descriptor angle at all - tracking-transparency is a pure async-function + permission
|
|
299
304
|
surface, never a view. Tests inject a fake native-module object in place of the real
|
|
300
305
|
`requireNativeModule` resolution (`src/core/*.test.ts`, `src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`,
|
|
301
|
-
`vitest`), the same pattern `expo-tracking-transparency` itself uses upstream
|
|
306
|
+
`vitest`), the same pattern `expo-tracking-transparency` itself uses upstream - no
|
|
302
307
|
`installFabric()` for the core layer, no ViewConfig. Native rendering itself is verified on-device
|
|
303
308
|
(see the parent [README](../../README.md) for the project's testing model).
|
|
304
309
|
|
|
305
310
|
## Known gaps
|
|
306
311
|
|
|
307
|
-
- Tests exercise the JS layer only (fake native module, `vitest`)
|
|
312
|
+
- Tests exercise the JS layer only (fake native module, `vitest`) - no on-device/simulator
|
|
308
313
|
automated smoke test yet, only manual verification.
|
package/build/angular/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { TrackingPermissionsService } from './tracking-permissions.service';
|
|
2
2
|
export * from '../core';
|
package/build/angular/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
export { PermissionsService } from './services/permissions.service/index.js';
|
|
1
|
+
// @symbiote-native/tracking-transparency/angular: the core plus `TrackingPermissionsService`
|
|
2
|
+
export { TrackingPermissionsService } from './tracking-permissions.service.js';
|
|
4
3
|
export * from '../core/index.js';
|
package/build/angular/{services/permissions.service/index.js → tracking-permissions.service.js}
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Angular twin of `../react`'s `useTrackingPermissions`: `inject(...).connect()` gives a signal
|
|
1
2
|
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
3
|
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
4
|
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
@@ -32,64 +33,28 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
33
|
}
|
|
33
34
|
return useValue ? value : void 0;
|
|
34
35
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
//
|
|
40
|
-
// readonly status = inject(PermissionsService).connect();
|
|
41
|
-
// // template: {{ status()?.granted }}
|
|
42
|
-
//
|
|
43
|
-
// The auto-fetch has nobody to reject to, so its failure lands in the `error` signal instead of
|
|
44
|
-
// escaping as an unhandled rejection: a null status with a non-null error is how a consumer tells
|
|
45
|
-
// "the fetch failed" from "not fetched yet". get()/request() still reject to their direct caller —
|
|
46
|
-
// only the automatic call is made safe.
|
|
47
|
-
import { Injectable, signal } from '@angular/core';
|
|
48
|
-
import { getTrackingPermissionsAsync, requestTrackingPermissionsAsync, } from '../../../core/index.js';
|
|
49
|
-
let PermissionsService = (() => {
|
|
36
|
+
import { Injectable } from '@angular/core';
|
|
37
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
38
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api.js';
|
|
39
|
+
let TrackingPermissionsService = (() => {
|
|
50
40
|
let _classDecorators = [Injectable({ providedIn: 'root' })];
|
|
51
41
|
let _classDescriptor;
|
|
52
42
|
let _classExtraInitializers = [];
|
|
53
43
|
let _classThis;
|
|
54
|
-
|
|
44
|
+
let _classSuper = PermissionsServiceBase;
|
|
45
|
+
var TrackingPermissionsService = class extends _classSuper {
|
|
55
46
|
static { _classThis = this; }
|
|
56
47
|
static {
|
|
57
|
-
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
48
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
58
49
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
59
|
-
|
|
50
|
+
TrackingPermissionsService = _classThis = _classDescriptor.value;
|
|
60
51
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
61
52
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
62
53
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
isAutoFetchStarted = false;
|
|
66
|
-
/** Why the auto-fetch left `status` at null. Cleared by the next successful get()/request(). */
|
|
67
|
-
error = this.fetchError.asReadonly();
|
|
68
|
-
connect() {
|
|
69
|
-
// Latched rather than guarded on `status() === null`: a failed fetch leaves status null
|
|
70
|
-
// forever, so the old guard turned every later connect() into another native call — unbounded
|
|
71
|
-
// once connect() is reached from a change-detected expression instead of a field initializer.
|
|
72
|
-
if (!this.isAutoFetchStarted) {
|
|
73
|
-
this.isAutoFetchStarted = true;
|
|
74
|
-
this.get().catch((cause) => {
|
|
75
|
-
this.fetchError.set(cause instanceof Error ? cause : new Error(String(cause)));
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return this.status.asReadonly();
|
|
79
|
-
}
|
|
80
|
-
async get() {
|
|
81
|
-
const response = await getTrackingPermissionsAsync();
|
|
82
|
-
this.status.set(response);
|
|
83
|
-
this.fetchError.set(null);
|
|
84
|
-
return response;
|
|
85
|
-
}
|
|
86
|
-
async request() {
|
|
87
|
-
const response = await requestTrackingPermissionsAsync();
|
|
88
|
-
this.status.set(response);
|
|
89
|
-
this.fetchError.set(null);
|
|
90
|
-
return response;
|
|
54
|
+
constructor() {
|
|
55
|
+
super(trackingPermissionMethods.getMethod, trackingPermissionMethods.requestMethod);
|
|
91
56
|
}
|
|
92
57
|
};
|
|
93
|
-
return
|
|
58
|
+
return TrackingPermissionsService = _classThis;
|
|
94
59
|
})();
|
|
95
|
-
export {
|
|
60
|
+
export { TrackingPermissionsService };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// `methods` every adapter's `useTrackingPermissions` binds to the shared
|
|
2
|
+
// `@symbiote-native/{react,vue,solid,svelte}` `createPermissionHook` factory
|
|
3
|
+
import { getTrackingPermissionsAsync, requestTrackingPermissionsAsync, } from './tracking-transparency.js';
|
|
4
|
+
export const trackingPermissionMethods = {
|
|
5
|
+
getMethod: getTrackingPermissionsAsync,
|
|
6
|
+
requestMethod: requestTrackingPermissionsAsync,
|
|
7
|
+
};
|
package/build/react/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useTrackingPermissions, type IUseTrackingPermissionsHook, } from './use-tracking-permissions';
|
|
2
2
|
export * from '../core';
|
package/build/react/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// @symbiote-native/tracking-transparency/react: the
|
|
2
|
-
|
|
3
|
-
// and refresh); getAdvertisingId/isAvailable are stateless, re-exported verbatim — mirrors the
|
|
4
|
-
// lifecycle-bucket naming convention of adapters/react/src/hooks.
|
|
5
|
-
export { usePermissions } from './hooks/use-permissions/index.js';
|
|
1
|
+
// @symbiote-native/tracking-transparency/react: the core plus `useTrackingPermissions`
|
|
2
|
+
export { useTrackingPermissions, } from './use-tracking-permissions.js';
|
|
6
3
|
export * from '../core/index.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
export type IUseTrackingPermissionsHook = (options?: IPermissionHookBehavior) => [
|
|
4
|
+
PermissionResponse | null,
|
|
5
|
+
() => Promise<PermissionResponse>,
|
|
6
|
+
() => Promise<PermissionResponse>
|
|
7
|
+
];
|
|
8
|
+
export declare const useTrackingPermissions: IUseTrackingPermissionsHook;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/react';
|
|
2
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api.js';
|
|
3
|
+
// React twin of `expo-tracking-transparency`'s `useTrackingPermissions`
|
|
4
|
+
export const useTrackingPermissions = createPermissionHook(trackingPermissionMethods);
|
package/build/solid/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useTrackingPermissions, type IUseTrackingPermissionsHook, } from './use-tracking-permissions';
|
|
2
2
|
export * from '../core';
|
package/build/solid/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// @symbiote-native/tracking-transparency/solid: the
|
|
2
|
-
|
|
3
|
-
// lifecycle primitive, every other export is a plain re-export — mirrors the lifecycle-bucket
|
|
4
|
-
// naming convention of adapters/solid/src/primitives (never `hooks/`/`composables/`/`runes/`,
|
|
5
|
-
// those are React's, Vue's and Svelte's terms).
|
|
6
|
-
export { createPermissions } from './primitives/create-permissions.js';
|
|
1
|
+
// @symbiote-native/tracking-transparency/solid: the core plus `useTrackingPermissions`
|
|
2
|
+
export { useTrackingPermissions, } from './use-tracking-permissions.js';
|
|
7
3
|
export * from '../core/index.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { Accessor } from 'solid-js';
|
|
4
|
+
export type IUseTrackingPermissionsHook = (options?: IPermissionHookBehavior) => [
|
|
5
|
+
Accessor<PermissionResponse | null>,
|
|
6
|
+
() => Promise<PermissionResponse>,
|
|
7
|
+
() => Promise<PermissionResponse>
|
|
8
|
+
];
|
|
9
|
+
export declare const useTrackingPermissions: IUseTrackingPermissionsHook;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/solid';
|
|
2
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api.js';
|
|
3
|
+
// Solid twin of `../react`'s `useTrackingPermissions`
|
|
4
|
+
export const useTrackingPermissions = createPermissionHook(trackingPermissionMethods);
|
package/build/svelte/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useTrackingPermissions, type IUseTrackingPermissionsHook, } from './use-tracking-permissions.svelte';
|
|
2
2
|
export * from '../core';
|
package/build/svelte/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// @symbiote-native/tracking-transparency/svelte: the
|
|
2
|
-
|
|
3
|
-
// every other export is a plain re-export — mirrors the lifecycle-bucket naming convention of
|
|
4
|
-
// adapters/svelte/src/runes (never `hooks/`/`composables/`, those are React's and Vue's terms).
|
|
5
|
-
export { usePermissions } from './runes/use-permissions.svelte';
|
|
1
|
+
// @symbiote-native/tracking-transparency/svelte: the core plus `useTrackingPermissions`
|
|
2
|
+
export { useTrackingPermissions, } from './use-tracking-permissions.svelte';
|
|
6
3
|
export * from '../core/index.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
export type IUseTrackingPermissionsHook = (options?: IPermissionHookBehavior) => {
|
|
4
|
+
readonly status: PermissionResponse | null;
|
|
5
|
+
requestPermission: () => Promise<PermissionResponse>;
|
|
6
|
+
getPermission: () => Promise<PermissionResponse>;
|
|
7
|
+
};
|
|
8
|
+
export declare const useTrackingPermissions: IUseTrackingPermissionsHook;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/svelte/runes/create-permission-hook';
|
|
2
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api.js';
|
|
3
|
+
// Svelte twin of `../react`'s `useTrackingPermissions`
|
|
4
|
+
export const useTrackingPermissions = createPermissionHook(trackingPermissionMethods);
|
package/build/vue/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useTrackingPermissions, type IUseTrackingPermissionsHook, } from './use-tracking-permissions';
|
|
2
2
|
export * from '../core';
|
package/build/vue/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// @symbiote-native/tracking-transparency/vue: the
|
|
2
|
-
|
|
3
|
-
// every other export is a plain re-export — mirrors the lifecycle-bucket naming convention of
|
|
4
|
-
// adapters/vue/src/composables (never `hooks/`, that's React's term).
|
|
5
|
-
export { usePermissions } from './composables/use-permissions/index.js';
|
|
1
|
+
// @symbiote-native/tracking-transparency/vue: the core plus `useTrackingPermissions`
|
|
2
|
+
export { useTrackingPermissions, } from './use-tracking-permissions.js';
|
|
6
3
|
export * from '../core/index.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PermissionResponse } from '../core';
|
|
2
|
+
import type { IPermissionHookBehavior } from '@symbiote-native/engine';
|
|
3
|
+
import type { Ref } from '@vue/runtime-core';
|
|
4
|
+
export type IUseTrackingPermissionsHook = (options?: IPermissionHookBehavior) => [
|
|
5
|
+
Ref<PermissionResponse | null>,
|
|
6
|
+
() => Promise<PermissionResponse>,
|
|
7
|
+
() => Promise<PermissionResponse>
|
|
8
|
+
];
|
|
9
|
+
export declare const useTrackingPermissions: IUseTrackingPermissionsHook;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createPermissionHook } from '@symbiote-native/vue';
|
|
2
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api.js';
|
|
3
|
+
// Vue twin of `../react`'s `useTrackingPermissions`
|
|
4
|
+
export const useTrackingPermissions = createPermissionHook(trackingPermissionMethods);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { TrackingPermissionsService } from './tracking-permissions.service';
|
|
2
2
|
export * from '../core';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
export { PermissionsService } from './services/permissions.service';
|
|
1
|
+
// @symbiote-native/tracking-transparency/angular: the core plus `TrackingPermissionsService`
|
|
2
|
+
export { TrackingPermissionsService } from './tracking-permissions.service';
|
|
4
3
|
export * from '../core';
|
|
5
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
2
|
+
import type { PermissionResponse } from '../core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class TrackingPermissionsService extends PermissionsServiceBase<PermissionResponse> {
|
|
5
|
+
constructor();
|
|
6
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TrackingPermissionsService, never>;
|
|
7
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<TrackingPermissionsService>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Angular twin of `../react`'s `useTrackingPermissions`: `inject(...).connect()` gives a signal
|
|
2
|
+
import { Injectable } from '@angular/core';
|
|
3
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
4
|
+
import { trackingPermissionMethods } from '../core/tracking-permission-api';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export class TrackingPermissionsService extends PermissionsServiceBase {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(trackingPermissionMethods.getMethod, trackingPermissionMethods.requestMethod);
|
|
9
|
+
}
|
|
10
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TrackingPermissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TrackingPermissionsService, providedIn: 'root' });
|
|
12
|
+
}
|
|
13
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TrackingPermissionsService, decorators: [{
|
|
14
|
+
type: Injectable,
|
|
15
|
+
args: [{ providedIn: 'root' }]
|
|
16
|
+
}], ctorParameters: () => [] });
|
|
17
|
+
//# sourceMappingURL=tracking-permissions.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking-permissions.service.js","sourceRoot":"","sources":["../../src/angular/tracking-permissions.service.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;;AAI5E,MAAM,OAAO,0BAA2B,SAAQ,sBAA0C;IACxF;QACE,KAAK,CACH,yBAAyB,CAAC,SAAS,EACnC,yBAAyB,CAAC,aAAa,CACxC,CAAC;IACJ,CAAC;uGANU,0BAA0B;2GAA1B,0BAA0B,cADb,MAAM;;2FACnB,0BAA0B;kBADtC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
|