@symbiote-native/background-task 0.1.2 → 0.1.3
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 +41 -27
- package/package.json +16 -16
package/README.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# @symbiote-native/background-task
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
[
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Sync, clean up or upload while the app is closed, when the OS decides the moment is right. One API
|
|
4
|
+
for every [SymbioteNative](../../README.md) adapter (React, Vue, Svelte, Solid and Angular).
|
|
5
|
+
|
|
6
|
+
It wraps [`expo-background-task`](https://github.com/expo/expo/tree/main/packages/expo-background-task).
|
|
7
|
+
Like [`@symbiote-native/task-manager`](../task-manager), every export is a plain function or a
|
|
8
|
+
one-time module-load side effect, so there is no hook, composable or service to wrap: every adapter
|
|
9
|
+
entry point is a plain re-export of the same `core`.
|
|
9
10
|
|
|
10
11
|
This is the modern replacement for [`@symbiote-native/background-fetch`](../background-fetch),
|
|
11
12
|
built on `BGTaskScheduler` (iOS) / `WorkManager` (Android) instead of a periodic-fetch alarm.
|
|
12
13
|
Like its sibling, this package registers a task with native so it fires **in the background on
|
|
13
|
-
the OS's own schedule**
|
|
14
|
+
the OS's own schedule** - it does not define what the task does. Define the task first via
|
|
14
15
|
[`@symbiote-native/task-manager`](../task-manager)'s `defineTask`, then register it for periodic
|
|
15
16
|
execution via this package's `registerTaskAsync`.
|
|
16
17
|
|
|
@@ -29,33 +30,33 @@ npx @symbiote-native/cli add --background-task
|
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
Either way: installs `@symbiote-native/background-task` + `@symbiote-native/task-manager` and
|
|
32
|
-
wires the native autolinking automatically
|
|
33
|
+
wires the native autolinking automatically - see [`@symbiote-native/cli`](../cli).
|
|
33
34
|
|
|
34
35
|
<details>
|
|
35
|
-
<summary>Manual install (no CLI
|
|
36
|
+
<summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
|
|
36
37
|
|
|
37
38
|
```bash
|
|
38
39
|
npm install @symbiote-native/background-task @symbiote-native/task-manager
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
`expo-background-task` and `expo-modules-core` come along as regular dependencies, pinned to
|
|
42
|
-
exact versions
|
|
43
|
+
exact versions - never install them yourself, and never add the `expo` meta-package to your
|
|
43
44
|
project.
|
|
44
45
|
|
|
45
46
|
## Required one-time step: native autolinking wiring
|
|
46
47
|
|
|
47
|
-
Same one-time step as every other `expo-modules-core` package this project ships
|
|
48
|
+
Same one-time step as every other `expo-modules-core` package this project ships - see
|
|
48
49
|
[`@symbiote-native/local-auth`'s README](../local-auth/README.md#required-one-time-step-native-autolinking-wiring)
|
|
49
50
|
and the `symbiote-expo-native-module` project skill.
|
|
50
51
|
|
|
51
52
|
iOS also needs `UIBackgroundModes: processing` and `BGTaskSchedulerPermittedIdentifiers` (the
|
|
52
53
|
fixed identifier baked into `expo-background-task`'s own native Swift source,
|
|
53
|
-
`BackgroundTaskConstants.swift`) in the app's Info.plist
|
|
54
|
+
`BackgroundTaskConstants.swift`) in the app's Info.plist - `native-link.json`'s `ios.infoPlistArrayKeys`
|
|
54
55
|
covers this ARRAY-valued case (see `@symbiote-native/expo-modules-link`), so it's wired
|
|
55
56
|
automatically by the same postinstall step, no manual edit needed. Android needs no manual step
|
|
56
57
|
either; its `AndroidManifest.xml` declares no extra permission.
|
|
57
58
|
|
|
58
|
-
**The iOS Simulator has no `BGTaskScheduler` support at all** (Apple's own limitation
|
|
59
|
+
**The iOS Simulator has no `BGTaskScheduler` support at all** (Apple's own limitation - physical
|
|
59
60
|
device only), so `BackgroundTaskStatus` reads `Restricted` there and `registerTaskAsync` is a
|
|
60
61
|
no-op regardless of Info.plist. Test registration on a real device.
|
|
61
62
|
|
|
@@ -69,7 +70,7 @@ src/core/ getStatusAsync / registerTaskAsync / unregisterTaskAsync /
|
|
|
69
70
|
BackgroundTaskStatus / BackgroundTaskResult / IBackgroundTaskOptions.
|
|
70
71
|
native-module.ts resolves the native module via expo-modules-core's
|
|
71
72
|
requireNativeModule.
|
|
72
|
-
src/angular/ @symbiote-native/background-task/angular
|
|
73
|
+
src/angular/ @symbiote-native/background-task/angular - export * from '../core'
|
|
73
74
|
```
|
|
74
75
|
|
|
75
76
|
`./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto
|
|
@@ -79,7 +80,7 @@ src/angular/ @symbiote-native/background-task/angular — export * from '../cor
|
|
|
79
80
|
## Use it
|
|
80
81
|
|
|
81
82
|
```ts
|
|
82
|
-
// index.ts, alongside AppRegistry.registerComponent
|
|
83
|
+
// index.ts, alongside AppRegistry.registerComponent - identical on every adapter
|
|
83
84
|
import { defineTask } from '@symbiote-native/task-manager';
|
|
84
85
|
import {
|
|
85
86
|
registerTaskAsync,
|
|
@@ -103,7 +104,7 @@ await registerTaskAsync(SYNC_TASK, { minimumInterval: 15 });
|
|
|
103
104
|
```
|
|
104
105
|
|
|
105
106
|
`@symbiote-native/task-manager` is the primitive both this package and
|
|
106
|
-
[`@symbiote-native/background-fetch`](../background-fetch) build on
|
|
107
|
+
[`@symbiote-native/background-fetch`](../background-fetch) build on - `defineTask` lives there,
|
|
107
108
|
`registerTaskAsync`/`unregisterTaskAsync` live here. `defineTask` must run at the top of the JS
|
|
108
109
|
bundle, outside any component, for the same reason documented in task-manager's own README: the
|
|
109
110
|
app can be launched headlessly to run a background task, with no views mounted.
|
|
@@ -117,7 +118,7 @@ import {
|
|
|
117
118
|
|
|
118
119
|
const status = await getStatusAsync();
|
|
119
120
|
|
|
120
|
-
// iOS only
|
|
121
|
+
// iOS only - the system can interrupt a running background task before it finishes.
|
|
121
122
|
const subscription = addExpirationListener(() => {
|
|
122
123
|
console.warn('background-sync was interrupted before it finished');
|
|
123
124
|
});
|
|
@@ -126,7 +127,7 @@ subscription.remove();
|
|
|
126
127
|
await unregisterTaskAsync(SYNC_TASK); // stop receiving executions of it
|
|
127
128
|
```
|
|
128
129
|
|
|
129
|
-
Identical import surface on every adapter
|
|
130
|
+
Identical import surface on every adapter - `@symbiote-native/background-task/react`,
|
|
130
131
|
`/vue`, `/svelte`, `/solid`, `/angular` all re-export the same functions.
|
|
131
132
|
|
|
132
133
|
## API
|
|
@@ -139,32 +140,45 @@ triggerTaskWorkerForTestingAsync(): Promise<boolean>
|
|
|
139
140
|
addExpirationListener(listener: () => void): { remove: () => void }
|
|
140
141
|
```
|
|
141
142
|
|
|
142
|
-
Plus `BackgroundTaskStatus`, `BackgroundTaskResult`, `IBackgroundTaskOptions`
|
|
143
|
+
Plus `BackgroundTaskStatus`, `BackgroundTaskResult`, `IBackgroundTaskOptions` - ported from
|
|
143
144
|
upstream's `BackgroundTask.types.ts`, the options type renamed with this repo's `I`-prefix
|
|
144
145
|
convention for exported types (`ts-js-best-practices`).
|
|
145
146
|
|
|
146
147
|
## Notes
|
|
147
148
|
|
|
148
149
|
- **`registerTaskAsync` requires the task to already be defined.** It throws if
|
|
149
|
-
`@symbiote-native/task-manager`'s `isTaskDefined(taskName)` is `false`
|
|
150
|
+
`@symbiote-native/task-manager`'s `isTaskDefined(taskName)` is `false` - call `defineTask`
|
|
150
151
|
first.
|
|
151
152
|
- **`registerTaskAsync` is a no-op, twice over.** It skips silently (with a one-time console
|
|
152
|
-
warning) when the environment reports `BackgroundTaskStatus.Restricted`
|
|
153
|
-
no `BGTaskScheduler` support at all
|
|
153
|
+
warning) when the environment reports `BackgroundTaskStatus.Restricted` - the iOS Simulator has
|
|
154
|
+
no `BGTaskScheduler` support at all - and it skips again, quietly, when the task is already
|
|
154
155
|
registered (checked via `@symbiote-native/task-manager`'s `isTaskRegisteredAsync`).
|
|
155
156
|
- **`triggerTaskWorkerForTestingAsync` only runs in a dev build.** It always resolves `false` in
|
|
156
|
-
production, matching upstream's own `__DEV__` gate
|
|
157
|
+
production, matching upstream's own `__DEV__` gate - read here through a narrow local type
|
|
157
158
|
rather than the bare RN global, since this package's own type graph never imports
|
|
158
159
|
`react-native`.
|
|
159
160
|
- **Expo Go is out of scope.** Upstream also warns when running inside Expo Go
|
|
160
161
|
(`isRunningInExpoGo`, imported from the `expo` meta-package) and reports
|
|
161
|
-
`BackgroundTaskStatus.Restricted` there. This project never installs `expo`
|
|
162
|
-
a bare/dev-client build, never Expo Go
|
|
162
|
+
`BackgroundTaskStatus.Restricted` there. This project never installs `expo` - every app here is
|
|
163
|
+
a bare/dev-client build, never Expo Go - so that branch has no equivalent here and is
|
|
163
164
|
intentionally not ported.
|
|
164
165
|
|
|
166
|
+
## Common questions
|
|
167
|
+
|
|
168
|
+
- **Nothing runs on the iOS Simulator.** Background tasks need a physical device.
|
|
169
|
+
- **`triggerTaskWorkerForTestingAsync` does nothing on iOS.** `BGTaskSchedulerPermittedIdentifiers`
|
|
170
|
+
must contain `com.expo.modules.backgroundtask.processing` in Info.plist; rebuild after adding it.
|
|
171
|
+
- **`minimumInterval`.** A hint only; the OS decides when to run.
|
|
172
|
+
- **Status ignores Background App Refresh on iOS.** Reported upstream; do not rely on it alone.
|
|
173
|
+
|
|
174
|
+
Sources: [Expo docs: BackgroundTask](https://docs.expo.dev/versions/latest/sdk/background-task/),
|
|
175
|
+
[expo/expo#40440](https://github.com/expo/expo/issues/40440),
|
|
176
|
+
[expo/expo#48786](https://github.com/expo/expo/issues/48786),
|
|
177
|
+
[expo/expo#35350](https://github.com/expo/expo/pull/35350).
|
|
178
|
+
|
|
165
179
|
## Test it
|
|
166
180
|
|
|
167
|
-
No Fabric/Descriptor angle at all
|
|
181
|
+
No Fabric/Descriptor angle at all - every function here is a pure async-function surface plus one
|
|
168
182
|
event subscription, never a view or per-instance state. Tests inject a fake native-module object
|
|
169
183
|
in place of the real `requireNativeModule` resolution and a fake `@symbiote-native/task-manager`
|
|
170
|
-
module (`src/core/background-task.test.ts`)
|
|
184
|
+
module (`src/core/background-task.test.ts`) - no `installFabric()`, no ViewConfig.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/background-task",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "expo-background-task wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Periodic background work via BGTaskScheduler (iOS) / WorkManager (Android), registered through @symbiote-native/task-manager.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"expo-background-task": "57.0.15",
|
|
75
|
-
"expo-modules-core": "57.0.
|
|
76
|
-
"@symbiote-native/task-manager": "0.1.
|
|
75
|
+
"expo-modules-core": "57.0.20",
|
|
76
|
+
"@symbiote-native/task-manager": "0.1.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"@angular/core": ">=20",
|
|
@@ -83,12 +83,12 @@
|
|
|
83
83
|
"solid-js": ">=1.9.0",
|
|
84
84
|
"svelte": ">=5.56.0",
|
|
85
85
|
"vue": ">=3.5.0",
|
|
86
|
-
"@symbiote-native/angular": "^3.
|
|
87
|
-
"@symbiote-native/engine": "^1.
|
|
88
|
-
"@symbiote-native/react": "^3.0
|
|
89
|
-
"@symbiote-native/solid": "^3.0
|
|
90
|
-
"@symbiote-native/svelte": "^3.0
|
|
91
|
-
"@symbiote-native/vue": "^3.0
|
|
86
|
+
"@symbiote-native/angular": "^3.2.0",
|
|
87
|
+
"@symbiote-native/engine": "^1.5.0",
|
|
88
|
+
"@symbiote-native/react": "^3.2.0",
|
|
89
|
+
"@symbiote-native/solid": "^3.1.0",
|
|
90
|
+
"@symbiote-native/svelte": "^3.1.0",
|
|
91
|
+
"@symbiote-native/vue": "^3.2.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependenciesMeta": {
|
|
94
94
|
"@symbiote-native/angular": {
|
|
@@ -136,13 +136,13 @@
|
|
|
136
136
|
"solid-js": "^1.9.14",
|
|
137
137
|
"svelte": "^5.56.0",
|
|
138
138
|
"typescript": "~6.0.0",
|
|
139
|
-
"@symbiote-native/angular": "3.
|
|
140
|
-
"@symbiote-native/engine": "1.
|
|
141
|
-
"@symbiote-native/react": "3.0
|
|
142
|
-
"@symbiote-native/solid": "3.0
|
|
143
|
-
"@symbiote-native/svelte": "3.0
|
|
144
|
-
"@symbiote-native/test-utils": "0.4.
|
|
145
|
-
"@symbiote-native/vue": "3.0
|
|
139
|
+
"@symbiote-native/angular": "3.2.0",
|
|
140
|
+
"@symbiote-native/engine": "1.5.0",
|
|
141
|
+
"@symbiote-native/react": "3.2.0",
|
|
142
|
+
"@symbiote-native/solid": "3.1.0",
|
|
143
|
+
"@symbiote-native/svelte": "3.1.0",
|
|
144
|
+
"@symbiote-native/test-utils": "0.4.6",
|
|
145
|
+
"@symbiote-native/vue": "3.2.0"
|
|
146
146
|
},
|
|
147
147
|
"scripts": {
|
|
148
148
|
"typecheck": "tsc --build",
|