@allstak/react-native 0.1.2 → 0.3.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
@@ -1,75 +1,225 @@
1
- # @allstak-io/react-native
1
+ # @allstak/react-native
2
2
 
3
- AllStak React Native SDK `ErrorUtils` + Hermes rejection tracking + Platform device tags.
4
- Includes native Android (Kotlin) and iOS (Swift) crash capture modules under `./native/`.
3
+ **Native crash + JS error capture for React Native. iOS and Android auto-wired.**
5
4
 
6
- ## Install
5
+ [![npm version](https://img.shields.io/npm/v/@allstak/react-native.svg)](https://www.npmjs.com/package/@allstak/react-native)
6
+ [![CI](https://github.com/allstak-io/allstak-react-native/actions/workflows/ci.yml/badge.svg)](https://github.com/allstak-io/allstak-react-native/actions)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
 
8
- > **Auth required:** GitHub Packages requires a token with `read:packages` scope.
9
+ Official AllStak SDK for React Native hooks `ErrorUtils`, Hermes rejection tracking, and native crash capture on iOS and Android.
9
10
 
10
- ### 1. Configure `.npmrc`
11
+ ## Dashboard
11
12
 
12
- ```ini
13
- @allstak-io:registry=https://npm.pkg.github.com
14
- //npm.pkg.github.com/:_authToken=YOUR_GITHUB_PAT
15
- ```
13
+ View captured events live at [app.allstak.sa](https://app.allstak.sa).
14
+
15
+ ![AllStak dashboard](https://app.allstak.sa/images/dashboard-preview.png)
16
+
17
+ ## Features
18
+
19
+ - `ErrorUtils.setGlobalHandler` integration for JS crash capture
20
+ - Hermes unhandled promise rejection tracking
21
+ - `Platform.OS` / `Platform.Version` auto-tags on every event
22
+ - Native layers (Obj-C/Swift, Java/Kotlin) ship under `native/` for fatal crash capture
23
+ - Breadcrumbs and user/tag context via the shared core API
24
+ - Works with RN 0.70+
25
+
26
+ ## What You Get
27
+
28
+ Once integrated, every event flows to your AllStak dashboard:
29
+
30
+ - **JS errors** — stack traces, component names, Hermes rejections
31
+ - **Native crashes** — iOS (Obj-C/Swift) and Android (Java/Kotlin) fatals
32
+ - **Logs** — structured logs with search and filters
33
+ - **HTTP** — outbound request timing, status codes, failed calls
34
+ - **Device tags** — `Platform.OS`, `Platform.Version`, release channel
35
+ - **Alerts** — email and webhook notifications on regressions
16
36
 
17
- ### 2. Install
37
+ ## Installation
18
38
 
19
39
  ```bash
20
- npm install @allstak-io/react-native@0.1.1 @allstak-io/core@0.1.1
21
- # react-native >=0.70 is an optional peer dep
40
+ npm install @allstak/react-native
22
41
  ```
23
42
 
24
- ## Usage
43
+ ## Quick Start
44
+
45
+ > Create a project at [app.allstak.sa](https://app.allstak.sa) to get your API key.
25
46
 
26
47
  ```ts
27
- import { AllStak } from '@allstak-io/core';
28
- import { installReactNative } from '@allstak-io/react-native';
48
+ import { Platform } from 'react-native';
49
+ import { AllStak, installReactNative } from '@allstak/react-native';
29
50
 
30
- // Initialize the base SDK
31
51
  AllStak.init({
32
52
  apiKey: process.env.ALLSTAK_API_KEY!,
33
53
  environment: 'production',
34
- release: 'v1.0.0',
35
- // ingest: 'https://api.allstak.sa' default
54
+ release: 'com.app@1.0.3+5',
55
+ dist: Platform.OS, // 'ios' | 'android' — used as the dashboard filter for binary builds
56
+ enableHttpTracking: true, // auto-instrument fetch + XHR + axios — see "HTTP tracking" below
36
57
  });
58
+ installReactNative(); // ErrorUtils + Hermes promise rejections + Platform tags
59
+
60
+ AllStak.captureException(new Error('test: hello from allstak-react-native'));
61
+ ```
62
+
63
+ Run the app — the test error appears in your dashboard within seconds.
64
+
65
+ ## HTTP tracking
66
+
67
+ Setting `enableHttpTracking: true` (off by default) auto-wraps `fetch`,
68
+ `XMLHttpRequest`, and `axios` (when the latter is installed) so every
69
+ outbound HTTP call is recorded as an `http_request` event.
37
70
 
38
- // Install RN-specific instrumentation
39
- installReactNative({
40
- // Hooks ErrorUtils for uncaught JS errors
41
- // Installs Hermes rejection tracking
42
- // Tags every event with Platform.OS and Platform.Version
71
+ **Privacy defaults are aggressive — `enableHttpTracking: true` is safe
72
+ to ship to production:**
73
+
74
+ - request bodies are **not** captured
75
+ - response bodies are **not** captured
76
+ - headers are **not** captured
77
+ - `Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, `X-Auth-Token`,
78
+ `Proxy-Authorization` are **always** redacted
79
+ - query params named `token`, `password`, `api_key`, `apikey`,
80
+ `authorization`, `auth`, `secret`, `access_token`, `refresh_token`,
81
+ `session`, `sessionid`, `jwt` are **always** redacted in the URL
82
+ - own-ingest URLs (your AllStak host) are skipped to avoid recursion
83
+
84
+ Enable richer capture only on routes you control:
85
+
86
+ ```ts
87
+ AllStak.init({
88
+ apiKey: '...',
89
+ enableHttpTracking: true,
90
+ httpTracking: {
91
+ captureRequestBody: true, // off by default
92
+ captureResponseBody: true, // off by default
93
+ captureHeaders: true, // off by default — auth headers still hard-redacted
94
+ redactHeaders: ['x-tenant'], // additional names on top of the always-redact list
95
+ redactQueryParams: ['custom_id'],
96
+ ignoredUrls: [/health/i, '/metrics'],
97
+ allowedUrls: [], // if non-empty, ONLY these URLs are captured
98
+ maxBodyBytes: 4096, // bodies truncated past this with `…[truncated]`
99
+ },
43
100
  });
44
101
  ```
45
102
 
46
- ## What's captured automatically after `installReactNative()`
103
+ ### axios
104
+
105
+ If the project uses axios with a non-XHR adapter (rare on RN), explicitly
106
+ instrument the instance — idempotent, so safe to call twice:
107
+
108
+ ```ts
109
+ import axios from 'axios';
110
+ const api = AllStak.instrumentAxios(axios.create({ baseURL: 'https://api.example.com' }));
111
+ ```
112
+
113
+ ### Errors auto-link to recent failed requests
114
+
115
+ When `enableHttpTracking: true` is on, the most recent failed HTTP
116
+ requests (status >= 400 or network error, last 10) are automatically
117
+ attached to the next `captureException` under
118
+ `metadata['http.recentFailed']`. Bodies are NOT included in this
119
+ snapshot unless body capture is enabled — only `method`, `url`,
120
+ `statusCode`, `durationMs`, `error`.
121
+
122
+ ### `dist`
123
+
124
+ `dist: Platform.OS` is the recommended pattern — it labels every event
125
+ with the binary build (`ios` / `android`) so the dashboard can filter
126
+ to a single platform when triaging.
127
+
128
+ ## Get Your API Key
129
+
130
+ 1. Sign up at [app.allstak.sa](https://app.allstak.sa)
131
+ 2. Create a project
132
+ 3. Copy your API key from **Project Settings → API Keys**
133
+ 4. Export it as `ALLSTAK_API_KEY` or pass it to `installReactNative(...)`
134
+
135
+ ## Configuration
136
+
137
+ | Option | Type | Required | Default | Description |
138
+ |---|---|---|---|---|
139
+ | `apiKey` | `string` | yes | — | Project API key (`ask_live_…`) |
140
+ | `environment` | `string` | no | — | Deployment env |
141
+ | `release` | `string` | no | — | App version |
142
+ | `host` | `string` | no | `https://api.allstak.sa` | Ingest host override |
143
+ | `user` | `{ id?, email? }` | no | — | Default user context |
144
+ | `tags` | `Record<string,string>` | no | — | Default tags |
145
+
146
+ ## Example Usage
147
+
148
+ Capture a caught exception:
149
+
150
+ ```ts
151
+ try {
152
+ await api.fetchFeed();
153
+ } catch (e) {
154
+ AllStak.captureException(e as Error, { screen: 'Feed' });
155
+ }
156
+ ```
157
+
158
+ Send a log from a screen:
159
+
160
+ ```ts
161
+ AllStak.captureMessage('User opened Settings', 'info');
162
+ ```
163
+
164
+ Tag the current build channel:
165
+
166
+ ```ts
167
+ AllStak.setTag('release-channel', 'beta');
168
+ AllStak.setUser({ id: userId });
169
+ ```
47
170
 
48
- | Capability | Notes |
49
- |-----------|-------|
50
- | Uncaught JS errors | Via `ErrorUtils.setGlobalHandler` |
51
- | Unhandled promise rejections | Via Hermes rejection tracking |
52
- | `Platform.OS` / `Platform.Version` tags | Attached to every event |
171
+ ## Production Endpoint
53
172
 
54
- ## Native crash capture (Android/iOS)
173
+ Production endpoint: `https://api.allstak.sa`. Override via `host` for self-hosted installs:
174
+
175
+ ```ts
176
+ installReactNative({ apiKey: '...', host: 'https://allstak.mycorp.com' });
177
+ ```
55
178
 
56
- Native modules for Java/Kotlin (Android) and Obj-C/Swift (iOS) crash capture are in `./native/`. See [`native/README.md`](./native/README.md) for platform-specific setup.
179
+ ## Source maps (Hermes / Metro)
180
+
181
+ JS bundles produced by Metro (with or without Hermes) are minified in
182
+ release builds — without source-map upload, your dashboard stacks will
183
+ read like `at e (index.bundle:1:42031)`. Wire it up once during release
184
+ build via `@allstak/js/sourcemaps` (devDependency only):
185
+
186
+ ```bash
187
+ npm install -D @allstak/js
188
+ ```
189
+
190
+ ```sh
191
+ # Build the release bundle as you normally would
192
+ npx react-native bundle \
193
+ --platform android --dev false --entry-file index.js \
194
+ --bundle-output android-release.bundle \
195
+ --sourcemap-output android-release.bundle.map
196
+
197
+ # Hermes-compile (if Hermes is enabled — the default on RN 0.70+)
198
+ hermes-compiler --emit-binary --output-source-map \
199
+ -out android-release.hbc android-release.bundle
200
+
201
+ # Upload to AllStak — debugId injection + map upload
202
+ node -e "import('@allstak/js/sourcemaps').then(({ processBuildOutput }) => \
203
+ processBuildOutput({ dir: '.', release: process.env.RELEASE, \
204
+ token: process.env.ALLSTAK_UPLOAD_TOKEN }))"
205
+ ```
57
206
 
58
- ## API
207
+ For iOS (`react-native bundle --platform ios`) the same flow applies.
208
+ Add this as a release-only step in your CI; the runtime SDK reads the
209
+ `debugId` from each frame and resolves the matching map server-side.
59
210
 
60
- | Export | Description |
61
- |--------|-------------|
62
- | `AllStak` | Re-exported from `@allstak-io/core` |
63
- | `installReactNative(opts?)` | Hooks ErrorUtils + Hermes + device tags |
64
- | `ReactNativeInstallOptions` | Options type for `installReactNative` |
211
+ > **Status:** the upload pipeline is the same one used by the web SDK
212
+ > and is unit-tested in `@allstak/js/tests/sourcemaps-*.test.ts`. Native
213
+ > Hermes-bytecode mapping has not yet been integration-tested end-to-end
214
+ > against the AllStak symbolicator on a real device build — flag any
215
+ > off-by-one source maps in [issues](https://github.com/AllStak/allstak-react-native/issues).
65
216
 
66
- ## GitHub Packages
217
+ ## Links
67
218
 
68
- - **Package:** `@allstak-io/react-native`
69
- - **Registry:** `https://npm.pkg.github.com`
70
- - **Repo:** [github.com/allstak-io/allstak-react-native](https://github.com/allstak-io/allstak-react-native)
71
- - **Releases:** [github.com/allstak-io/allstak-react-native/releases](https://github.com/allstak-io/allstak-react-native/releases)
219
+ - Documentation: https://docs.allstak.sa
220
+ - Dashboard: https://app.allstak.sa
221
+ - Source: https://github.com/allstak-io/allstak-react-native
72
222
 
73
- ## Versioning
223
+ ## License
74
224
 
75
- Tags must match `package.json` version exactly (e.g. `v0.1.1`). The release workflow fails if there's a mismatch.
225
+ MIT © AllStak
package/app.plugin.js ADDED
@@ -0,0 +1,6 @@
1
+ // Expo entrypoint — re-exports the actual plugin from `dist/expo-plugin.js`
2
+ // so consumers can write `"plugins": ["@allstak/react-native"]` in their
3
+ // app.json and Expo's `withPlugins` resolver finds it without an extra
4
+ // import path. Expo looks for `app.plugin.js` at the package root by
5
+ // convention.
6
+ module.exports = require('./dist/expo-plugin.js');
@@ -0,0 +1,11 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
11
+ //# sourceMappingURL=chunk-BJTO5JO5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Expo config plugin.
3
+ *
4
+ * Apply via `app.json`:
5
+ *
6
+ * {
7
+ * "expo": {
8
+ * "plugins": [
9
+ * ["@allstak/react-native", { "release": "mobile@1.2.3", "environment": "production" }]
10
+ * ]
11
+ * }
12
+ * }
13
+ *
14
+ * The plugin runs at `expo prebuild` / EAS build time and:
15
+ *
16
+ * 1. Adds the AllStak iOS pod (declared in `react-native.config.js`).
17
+ * Expo's autolinking already picks this up — we just record metadata
18
+ * so `expo doctor` can verify the install is wired.
19
+ * 2. Stamps the chosen `release` into `expo-constants` extras so the JS
20
+ * layer can read it at runtime via `Constants.expoConfig.extra._allstak`
21
+ * without the host app needing to plumb it through env vars.
22
+ * 3. Records that `@allstak/react-native` was loaded as an Expo plugin
23
+ * for diagnostics.
24
+ *
25
+ * Pure config mutation — no native code is patched here. The native iOS
26
+ * + Android modules under ./native are linked by Expo's existing
27
+ * autolinking flow (which honors the `react-native.config.js` manifest).
28
+ */
29
+ interface AllStakExpoOptions {
30
+ /** Release identifier (e.g. `mobile@1.2.3`). Stamped into `Constants.expoConfig.extra._allstak.release`. */
31
+ release?: string;
32
+ /** Environment label — `production`, `staging`, etc. */
33
+ environment?: string;
34
+ /** Optional dist tag (e.g. `ios-hermes`). Auto-detected at runtime if unset. */
35
+ dist?: string;
36
+ }
37
+ interface ExpoConfig {
38
+ name?: string;
39
+ extra?: Record<string, unknown>;
40
+ plugins?: any[];
41
+ [key: string]: any;
42
+ }
43
+ interface ExpoConfigContext {
44
+ modResults?: any;
45
+ modRawConfig?: ExpoConfig;
46
+ [key: string]: any;
47
+ }
48
+ /**
49
+ * The plugin function itself. Expo's plugin runner calls it as
50
+ * `(config, options) => modifiedConfig`. We avoid importing
51
+ * `@expo/config-plugins` so the package has zero hard dependencies on the
52
+ * Expo toolchain — the type checking happens at usage site instead.
53
+ */
54
+ declare function withAllStak(config: ExpoConfig & ExpoConfigContext, options?: AllStakExpoOptions): ExpoConfig;
55
+
56
+ export { type AllStakExpoOptions, withAllStak as default };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Expo config plugin.
3
+ *
4
+ * Apply via `app.json`:
5
+ *
6
+ * {
7
+ * "expo": {
8
+ * "plugins": [
9
+ * ["@allstak/react-native", { "release": "mobile@1.2.3", "environment": "production" }]
10
+ * ]
11
+ * }
12
+ * }
13
+ *
14
+ * The plugin runs at `expo prebuild` / EAS build time and:
15
+ *
16
+ * 1. Adds the AllStak iOS pod (declared in `react-native.config.js`).
17
+ * Expo's autolinking already picks this up — we just record metadata
18
+ * so `expo doctor` can verify the install is wired.
19
+ * 2. Stamps the chosen `release` into `expo-constants` extras so the JS
20
+ * layer can read it at runtime via `Constants.expoConfig.extra._allstak`
21
+ * without the host app needing to plumb it through env vars.
22
+ * 3. Records that `@allstak/react-native` was loaded as an Expo plugin
23
+ * for diagnostics.
24
+ *
25
+ * Pure config mutation — no native code is patched here. The native iOS
26
+ * + Android modules under ./native are linked by Expo's existing
27
+ * autolinking flow (which honors the `react-native.config.js` manifest).
28
+ */
29
+ interface AllStakExpoOptions {
30
+ /** Release identifier (e.g. `mobile@1.2.3`). Stamped into `Constants.expoConfig.extra._allstak.release`. */
31
+ release?: string;
32
+ /** Environment label — `production`, `staging`, etc. */
33
+ environment?: string;
34
+ /** Optional dist tag (e.g. `ios-hermes`). Auto-detected at runtime if unset. */
35
+ dist?: string;
36
+ }
37
+ interface ExpoConfig {
38
+ name?: string;
39
+ extra?: Record<string, unknown>;
40
+ plugins?: any[];
41
+ [key: string]: any;
42
+ }
43
+ interface ExpoConfigContext {
44
+ modResults?: any;
45
+ modRawConfig?: ExpoConfig;
46
+ [key: string]: any;
47
+ }
48
+ /**
49
+ * The plugin function itself. Expo's plugin runner calls it as
50
+ * `(config, options) => modifiedConfig`. We avoid importing
51
+ * `@expo/config-plugins` so the package has zero hard dependencies on the
52
+ * Expo toolchain — the type checking happens at usage site instead.
53
+ */
54
+ declare function withAllStak(config: ExpoConfig & ExpoConfigContext, options?: AllStakExpoOptions): ExpoConfig;
55
+
56
+ export { type AllStakExpoOptions, withAllStak as default };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/expo-plugin.ts
21
+ var expo_plugin_exports = {};
22
+ __export(expo_plugin_exports, {
23
+ default: () => expo_plugin_default
24
+ });
25
+ module.exports = __toCommonJS(expo_plugin_exports);
26
+ function withAllStak(config, options = {}) {
27
+ const next = { ...config };
28
+ next.extra = { ...config.extra ?? {} };
29
+ const existing = next.extra._allstak ?? {};
30
+ next.extra._allstak = {
31
+ ...existing,
32
+ release: options.release ?? existing.release,
33
+ environment: options.environment ?? existing.environment,
34
+ dist: options.dist ?? existing.dist,
35
+ pluginVersion: "0.3.0"
36
+ };
37
+ return next;
38
+ }
39
+ var expo_plugin_default = withAllStak;
40
+ if (typeof module !== "undefined" && module.exports) {
41
+ module.exports = withAllStak;
42
+ module.exports.default = withAllStak;
43
+ }
44
+ //# sourceMappingURL=expo-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/expo-plugin.ts"],"sourcesContent":["/**\n * Expo config plugin.\n *\n * Apply via `app.json`:\n *\n * {\n * \"expo\": {\n * \"plugins\": [\n * [\"@allstak/react-native\", { \"release\": \"mobile@1.2.3\", \"environment\": \"production\" }]\n * ]\n * }\n * }\n *\n * The plugin runs at `expo prebuild` / EAS build time and:\n *\n * 1. Adds the AllStak iOS pod (declared in `react-native.config.js`).\n * Expo's autolinking already picks this up — we just record metadata\n * so `expo doctor` can verify the install is wired.\n * 2. Stamps the chosen `release` into `expo-constants` extras so the JS\n * layer can read it at runtime via `Constants.expoConfig.extra._allstak`\n * without the host app needing to plumb it through env vars.\n * 3. Records that `@allstak/react-native` was loaded as an Expo plugin\n * for diagnostics.\n *\n * Pure config mutation — no native code is patched here. The native iOS\n * + Android modules under ./native are linked by Expo's existing\n * autolinking flow (which honors the `react-native.config.js` manifest).\n */\n\nexport interface AllStakExpoOptions {\n /** Release identifier (e.g. `mobile@1.2.3`). Stamped into `Constants.expoConfig.extra._allstak.release`. */\n release?: string;\n /** Environment label — `production`, `staging`, etc. */\n environment?: string;\n /** Optional dist tag (e.g. `ios-hermes`). Auto-detected at runtime if unset. */\n dist?: string;\n}\n\ninterface ExpoConfig {\n name?: string;\n extra?: Record<string, unknown>;\n plugins?: any[];\n [key: string]: any;\n}\n\ninterface ExpoConfigContext {\n modResults?: any;\n modRawConfig?: ExpoConfig;\n [key: string]: any;\n}\n\n/**\n * The plugin function itself. Expo's plugin runner calls it as\n * `(config, options) => modifiedConfig`. We avoid importing\n * `@expo/config-plugins` so the package has zero hard dependencies on the\n * Expo toolchain — the type checking happens at usage site instead.\n */\nfunction withAllStak(config: ExpoConfig & ExpoConfigContext, options: AllStakExpoOptions = {}): ExpoConfig {\n const next: ExpoConfig = { ...config };\n next.extra = { ...(config.extra ?? {}) };\n\n // Embed runtime-readable metadata under a namespaced key so we never\n // collide with the host app's other extras.\n const existing = (next.extra as any)._allstak ?? {};\n (next.extra as any)._allstak = {\n ...existing,\n release: options.release ?? existing.release,\n environment: options.environment ?? existing.environment,\n dist: options.dist ?? existing.dist,\n pluginVersion: '0.3.0',\n };\n\n return next;\n}\n\nexport default withAllStak;\n\n// Expose as a CommonJS function so `app.plugin.js`'s `require('./dist/expo-plugin.js')`\n// returns the plugin directly. The `declare const module` keeps the TS\n// type-checker happy without dragging in @types/node.\ndeclare const module: { exports: any };\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = withAllStak;\n module.exports.default = withAllStak;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDA,SAAS,YAAY,QAAwC,UAA8B,CAAC,GAAe;AACzG,QAAM,OAAmB,EAAE,GAAG,OAAO;AACrC,OAAK,QAAQ,EAAE,GAAI,OAAO,SAAS,CAAC,EAAG;AAIvC,QAAM,WAAY,KAAK,MAAc,YAAY,CAAC;AAClD,EAAC,KAAK,MAAc,WAAW;AAAA,IAC7B,GAAG;AAAA,IACH,SAAS,QAAQ,WAAW,SAAS;AAAA,IACrC,aAAa,QAAQ,eAAe,SAAS;AAAA,IAC7C,MAAM,QAAQ,QAAQ,SAAS;AAAA,IAC/B,eAAe;AAAA,EACjB;AAEA,SAAO;AACT;AAEA,IAAO,sBAAQ;AAMf,IAAI,OAAO,WAAW,eAAe,OAAO,SAAS;AACnD,SAAO,UAAU;AACjB,SAAO,QAAQ,UAAU;AAC3B;","names":[]}
@@ -0,0 +1,25 @@
1
+ import "./chunk-BJTO5JO5.mjs";
2
+
3
+ // src/expo-plugin.ts
4
+ function withAllStak(config, options = {}) {
5
+ const next = { ...config };
6
+ next.extra = { ...config.extra ?? {} };
7
+ const existing = next.extra._allstak ?? {};
8
+ next.extra._allstak = {
9
+ ...existing,
10
+ release: options.release ?? existing.release,
11
+ environment: options.environment ?? existing.environment,
12
+ dist: options.dist ?? existing.dist,
13
+ pluginVersion: "0.3.0"
14
+ };
15
+ return next;
16
+ }
17
+ var expo_plugin_default = withAllStak;
18
+ if (typeof module !== "undefined" && module.exports) {
19
+ module.exports = withAllStak;
20
+ module.exports.default = withAllStak;
21
+ }
22
+ export {
23
+ expo_plugin_default as default
24
+ };
25
+ //# sourceMappingURL=expo-plugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/expo-plugin.ts"],"sourcesContent":["/**\n * Expo config plugin.\n *\n * Apply via `app.json`:\n *\n * {\n * \"expo\": {\n * \"plugins\": [\n * [\"@allstak/react-native\", { \"release\": \"mobile@1.2.3\", \"environment\": \"production\" }]\n * ]\n * }\n * }\n *\n * The plugin runs at `expo prebuild` / EAS build time and:\n *\n * 1. Adds the AllStak iOS pod (declared in `react-native.config.js`).\n * Expo's autolinking already picks this up — we just record metadata\n * so `expo doctor` can verify the install is wired.\n * 2. Stamps the chosen `release` into `expo-constants` extras so the JS\n * layer can read it at runtime via `Constants.expoConfig.extra._allstak`\n * without the host app needing to plumb it through env vars.\n * 3. Records that `@allstak/react-native` was loaded as an Expo plugin\n * for diagnostics.\n *\n * Pure config mutation — no native code is patched here. The native iOS\n * + Android modules under ./native are linked by Expo's existing\n * autolinking flow (which honors the `react-native.config.js` manifest).\n */\n\nexport interface AllStakExpoOptions {\n /** Release identifier (e.g. `mobile@1.2.3`). Stamped into `Constants.expoConfig.extra._allstak.release`. */\n release?: string;\n /** Environment label — `production`, `staging`, etc. */\n environment?: string;\n /** Optional dist tag (e.g. `ios-hermes`). Auto-detected at runtime if unset. */\n dist?: string;\n}\n\ninterface ExpoConfig {\n name?: string;\n extra?: Record<string, unknown>;\n plugins?: any[];\n [key: string]: any;\n}\n\ninterface ExpoConfigContext {\n modResults?: any;\n modRawConfig?: ExpoConfig;\n [key: string]: any;\n}\n\n/**\n * The plugin function itself. Expo's plugin runner calls it as\n * `(config, options) => modifiedConfig`. We avoid importing\n * `@expo/config-plugins` so the package has zero hard dependencies on the\n * Expo toolchain — the type checking happens at usage site instead.\n */\nfunction withAllStak(config: ExpoConfig & ExpoConfigContext, options: AllStakExpoOptions = {}): ExpoConfig {\n const next: ExpoConfig = { ...config };\n next.extra = { ...(config.extra ?? {}) };\n\n // Embed runtime-readable metadata under a namespaced key so we never\n // collide with the host app's other extras.\n const existing = (next.extra as any)._allstak ?? {};\n (next.extra as any)._allstak = {\n ...existing,\n release: options.release ?? existing.release,\n environment: options.environment ?? existing.environment,\n dist: options.dist ?? existing.dist,\n pluginVersion: '0.3.0',\n };\n\n return next;\n}\n\nexport default withAllStak;\n\n// Expose as a CommonJS function so `app.plugin.js`'s `require('./dist/expo-plugin.js')`\n// returns the plugin directly. The `declare const module` keeps the TS\n// type-checker happy without dragging in @types/node.\ndeclare const module: { exports: any };\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = withAllStak;\n module.exports.default = withAllStak;\n}\n"],"mappings":";;;AAyDA,SAAS,YAAY,QAAwC,UAA8B,CAAC,GAAe;AACzG,QAAM,OAAmB,EAAE,GAAG,OAAO;AACrC,OAAK,QAAQ,EAAE,GAAI,OAAO,SAAS,CAAC,EAAG;AAIvC,QAAM,WAAY,KAAK,MAAc,YAAY,CAAC;AAClD,EAAC,KAAK,MAAc,WAAW;AAAA,IAC7B,GAAG;AAAA,IACH,SAAS,QAAQ,WAAW,SAAS;AAAA,IACrC,aAAa,QAAQ,eAAe,SAAS;AAAA,IAC7C,MAAM,QAAQ,QAAQ,SAAS;AAAA,IAC/B,eAAe;AAAA,EACjB;AAEA,SAAO;AACT;AAEA,IAAO,sBAAQ;AAMf,IAAI,OAAO,WAAW,eAAe,OAAO,SAAS;AACnD,SAAO,UAAU;AACjB,SAAO,QAAQ,UAAU;AAC3B;","names":[]}