@symbiote-native/sms 3.0.1 → 3.0.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.
Files changed (2) hide show
  1. package/README.md +40 -25
  2. package/package.json +15 -15
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # @symbiote-native/sms
2
2
 
3
- A wrapper package for [SymbioteNative](../../README.md) that makes
4
- [`expo-sms`](https://github.com/expo/expo/tree/main/packages/expo-sms) — opening the system SMS
5
- composer prefilled with recipients, a message, and optionally an attachment — usable from
6
- **every** adapter, React, Vue, Svelte, Solid, and Angular, not just React. Built the same way as
7
- [`@symbiote-native/secure-store`](../secure-store): an `expo-modules-core`-based wrapper (see the
8
- `symbiote-expo-native-module` project skill for the full mechanism — why `expo-modules-core` is
9
- depended on directly and never the `expo` meta-package, why the upstream JS is hand-ported into
10
- `core/` rather than imported, and how autolinking picks up the native module).
3
+ Open the system SMS composer with recipients, a message and optionally an attachment already
4
+ filled in. One API for every [SymbioteNative](../../README.md) adapter (React, Vue, Svelte, Solid
5
+ and Angular).
6
+
7
+ It wraps [`expo-sms`](https://github.com/expo/expo/tree/main/packages/expo-sms) the same way
8
+ [`@symbiote-native/secure-store`](../secure-store) wraps its upstream: `expo-modules-core` is a
9
+ direct dependency, never the `expo` meta-package, and the upstream JS is hand-ported into `core/`.
10
+ The mechanics live in the `symbiote-expo-native-module` project skill.
11
11
 
12
12
  Nothing is ever sent on the user's behalf. Both platforms open their own composer with the draft
13
13
  filled in; the user presses send, edits, or discards it.
@@ -26,35 +26,35 @@ npx @symbiote-native/cli new my-app --sms
26
26
  npx @symbiote-native/cli add --sms
27
27
  ```
28
28
 
29
- Either way: installs `@symbiote-native/sms` and wires the native autolinking automatically — see
29
+ Either way: installs `@symbiote-native/sms` and wires the native autolinking automatically - see
30
30
  [`@symbiote-native/cli`](../cli).
31
31
 
32
32
  <details>
33
- <summary>Manual install (no CLI — installing and wiring native autolinking by hand)</summary>
33
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
34
34
 
35
35
  ```bash
36
36
  npm install @symbiote-native/sms
37
37
  ```
38
38
 
39
- `expo-sms` and `expo-modules-core` come along as regular, pinned dependencies — never install
39
+ `expo-sms` and `expo-modules-core` come along as regular, pinned dependencies - never install
40
40
  either yourself, and never add the `expo` meta-package to this project (it bundles its own
41
41
  Metro/Babel pipeline that conflicts with this project's own).
42
42
 
43
43
  ### Required one-time step: native autolinking wiring
44
44
 
45
45
  Unlike a plain RN native module, `expo-sms`'s native code is discovered by
46
- `expo-modules-autolinking` — this needs wiring into the native host app **once**, covering this
46
+ `expo-modules-autolinking` - this needs wiring into the native host app **once**, covering this
47
47
  package and every other `expo-modules-core` package with zero further changes:
48
48
 
49
49
  | Platform | Touches |
50
50
  | -------- | ------------------------------------------------------------------------------------- |
51
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
52
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
53
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
54
- | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a native-module name map |
51
+ | iOS | `ios/Podfile` - add `use_expo_modules!` |
52
+ | iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
53
+ | Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
54
+ | Android | `MainApplication.kt` - Expo's bootstrap hook, plus a native-module name map |
55
55
 
56
56
  Full mechanics live in the `symbiote-expo-native-module` skill. The per-package half of that
57
- table — the Gradle dependency and the module map entry — is generated by
57
+ table - the Gradle dependency and the module map entry - is generated by
58
58
  [`@symbiote-native/expo-modules-link`](../expo-modules-link) from this package's
59
59
  `native-link.json` on every install.
60
60
 
@@ -63,7 +63,7 @@ table — the Gradle dependency and the module map entry — is generated by
63
63
  This is the least invasive of the Expo wrappers here:
64
64
 
65
65
  - **No runtime permission on either platform.** Opening the composer is an intent
66
- (`ACTION_SENDTO`/`ACTION_SEND`) on Android and an `MFMessageComposeViewController` on iOS —
66
+ (`ACTION_SENDTO`/`ACTION_SEND`) on Android and an `MFMessageComposeViewController` on iOS -
67
67
  the user's own app does the sending, so neither platform asks for one. `expo-sms` requests no
68
68
  permission anywhere in its native code, and reading the _outcome_ of a sent message on Android
69
69
  would need `READ_SMS`, which is exactly why it doesn't try (see the `unknown` result below).
@@ -83,9 +83,9 @@ src/core/ the whole API: sendSMSAsync + isAvailableAsync. native
83
83
  src/angular/ @symbiote-native/sms/angular
84
84
  ```
85
85
 
86
- `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto `src/core/` —
87
- no physical per-framework file. Both exports are stateless free functions — `sendSMSAsync` resolves
88
- once the composer closes and holds nothing afterwards, and there is no event stream — so there is
86
+ `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto `src/core/` -
87
+ no physical per-framework file. Both exports are stateless free functions - `sendSMSAsync` resolves
88
+ once the composer closes and holds nothing afterwards, and there is no event stream - so there is
89
89
  nothing for a hook, composable, or service to wrap, the same reason
90
90
  [`@symbiote-native/secure-store`](../secure-store) does the same. `./angular` stays a physical
91
91
  file/subpath since Angular ships through a separate `ngc`/AOT build (`build-ngc/`). Import from
@@ -106,7 +106,7 @@ if (await isAvailableAsync()) {
106
106
  }
107
107
  ```
108
108
 
109
- A single recipient may be passed as a bare string — it is normalised into an array before the
109
+ A single recipient may be passed as a bare string - it is normalised into an array before the
110
110
  native call:
111
111
 
112
112
  ```ts
@@ -125,7 +125,7 @@ await sendSMSAsync('0123456789', 'Here is the receipt', {
125
125
  });
126
126
  ```
127
127
 
128
- The `uri` has to be a **content** URI — the composer runs in another app's process, and a plain
128
+ The `uri` has to be a **content** URI - the composer runs in another app's process, and a plain
129
129
  file path is not readable from there.
130
130
 
131
131
  ## API
@@ -135,12 +135,14 @@ file path is not readable from there.
135
135
  | `isAvailableAsync` | `() => Promise<boolean>` | `false` on the iOS simulator, which has no Messages app, and on Android devices without telephony hardware. |
136
136
  | `sendSMSAsync` | `(addresses, message, options?) => Promise<ISmsResponse>` | Opens the composer. Resolves when it closes. Throws if the device has no messaging app. |
137
137
 
138
- `ISmsOptions`: `attachments` — one `ISmsAttachment` or a list of them.
138
+ `ISmsOptions`: `attachments` - one `ISmsAttachment` or a list of them.
139
139
  `ISmsAttachment`: `uri` (content URI), `mimeType`, `filename`.
140
140
  `ISmsResponse`: `{ result: 'sent' | 'cancelled' | 'unknown' }`.
141
141
 
142
142
  ## Notes
143
143
 
144
+ - **Check `isAvailableAsync()` first.** It resolves `false` on devices that cannot send text, such as
145
+ an iOS simulator or a tablet without telephony, and `sendSMSAsync` rejects there.
144
146
  - **Android always resolves `unknown`.** The only way to learn whether a message actually left
145
147
  the device is to query the SMS database, which needs the `READ_SMS` permission Google restricts
146
148
  to default-SMS-app publishers. Treat `unknown` as "the composer closed", not as a failure.
@@ -150,12 +152,25 @@ file path is not readable from there.
150
152
  - **`sendSMSAsync` can reject.** Android throws when no messaging application is installed; iOS
151
153
  throws when the device cannot send text at all, or when a composer is already open.
152
154
 
155
+ ## Common questions
156
+
157
+ - **`isAvailableAsync()` is `false` on the iOS Simulator.** Expected: it cannot send text.
158
+ - **Android: "No messaging application available".** No installed app handled the intent; the
159
+ package ships the Android 11 `<queries>` entries, so check a messaging app exists.
160
+ - **Silent send?** No: the user presses send in the system composer.
161
+ - **Result is not `sent` on Android.** It always resolves `unknown`.
162
+ - **One attachment arrives on Android.** The composer takes one; iOS attaches all.
163
+
164
+ Sources: [Expo docs: SMS](https://docs.expo.dev/versions/latest/sdk/sms/),
165
+ [expo/expo#13277](https://github.com/expo/expo/issues/13277),
166
+ [expo/expo#2384](https://github.com/expo/expo/issues/2384).
167
+
153
168
  ## Test it
154
169
 
155
170
  ```bash
156
171
  pnpm vitest run packages/sms
157
172
  ```
158
173
 
159
- The core tests fake the native module in place of `requireNativeModule`'s runtime resolution —
174
+ The core tests fake the native module in place of `requireNativeModule`'s runtime resolution -
160
175
  `ExpoSMS` only exists on a device, so a headless run would otherwise throw at import. The
161
176
  composer itself, and the `sent`/`cancelled` distinction, can only be verified on a device.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/sms",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "expo-sms wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Opens the system SMS composer prefilled with recipients and a message.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "expo-sms": "57.0.1",
73
- "expo-modules-core": "57.0.5"
73
+ "expo-modules-core": "57.0.20"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@angular/core": ">=20",
@@ -80,12 +80,12 @@
80
80
  "solid-js": ">=1.9.0",
81
81
  "svelte": ">=5.56.0",
82
82
  "vue": ">=3.5.0",
83
- "@symbiote-native/angular": "^3.1.1",
84
- "@symbiote-native/engine": "^1.3.0",
85
- "@symbiote-native/react": "^3.0.3",
86
- "@symbiote-native/solid": "^3.0.3",
87
- "@symbiote-native/svelte": "^3.0.3",
88
- "@symbiote-native/vue": "^3.0.3"
83
+ "@symbiote-native/angular": "^3.2.0",
84
+ "@symbiote-native/engine": "^1.5.0",
85
+ "@symbiote-native/react": "^3.2.0",
86
+ "@symbiote-native/solid": "^3.1.0",
87
+ "@symbiote-native/svelte": "^3.1.0",
88
+ "@symbiote-native/vue": "^3.2.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "@symbiote-native/angular": {
@@ -133,13 +133,13 @@
133
133
  "solid-js": "^1.9.14",
134
134
  "svelte": "^5.56.0",
135
135
  "typescript": "~6.0.0",
136
- "@symbiote-native/angular": "3.1.1",
137
- "@symbiote-native/engine": "1.3.0",
138
- "@symbiote-native/react": "3.0.3",
139
- "@symbiote-native/solid": "3.0.3",
140
- "@symbiote-native/svelte": "3.0.3",
141
- "@symbiote-native/test-utils": "0.4.3",
142
- "@symbiote-native/vue": "3.0.3"
136
+ "@symbiote-native/angular": "3.2.0",
137
+ "@symbiote-native/engine": "1.5.0",
138
+ "@symbiote-native/react": "3.2.0",
139
+ "@symbiote-native/solid": "3.1.0",
140
+ "@symbiote-native/svelte": "3.1.0",
141
+ "@symbiote-native/test-utils": "0.4.6",
142
+ "@symbiote-native/vue": "3.2.0"
143
143
  },
144
144
  "scripts": {
145
145
  "typecheck": "tsc --build",