@allstak/react 0.3.2 → 0.3.4

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,392 +1,165 @@
1
1
  # @allstak/react
2
2
 
3
- **One wrapper. Full error tracking + Web Vitals + breadcrumbs + HTTP. For React 17, 18, and 19.**
3
+ AllStak React SDK for browser error capture, component error boundaries, breadcrumbs, user context, HTTP metadata, traces, Web Vitals, and source-map release support.
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/@allstak/react.svg)](https://www.npmjs.com/package/@allstak/react)
6
- [![CI](https://github.com/AllStak/allstak-react/actions/workflows/ci.yml/badge.svg)](https://github.com/AllStak/allstak-react/actions)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ Stability: stable SDK runtime, beta live certification. Live dashboard proof is not claimed until you run a project with real AllStak credentials.
8
6
 
9
- Official AllStak SDK for React — provider component, error boundary, hooks, and Web Vitals on top of a self-contained browser client.
7
+ ## 1. Automatic Setup With Wizard
10
8
 
11
- ## Dashboard
9
+ Recommended flow:
12
10
 
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
- - **One-wrapper setup** — `<AllStakProvider>` initializes everything
20
- - React error boundary with custom fallback UI + `resetError`
21
- - `window.onerror` + `unhandledrejection` capture
22
- - `console.warn` + `console.error` capture by default; `log`/`info` opt-in
23
- - `fetch` and `XMLHttpRequest` breadcrumbs (200 / 4xx / 5xx / network failure)
24
- - Full HTTP request events with `enableHttpTracking: true` + privacy-first redaction
25
- - Auto navigation breadcrumbs (history.pushState patch + popstate)
26
- - Web Vitals via PerformanceObserver (CLS / LCP / INP / FCP / TTFB)
27
- - React Router + Next.js helpers
28
- - `useAllStak()` hook with stable identity
29
- - Full TypeScript types
30
-
31
- ## Quick Start
32
-
33
- > **Time to first event: under 2 minutes.**
34
- > Create a project at [app.allstak.sa](https://app.allstak.sa) to get your API key.
11
+ ```bash
12
+ npx @allstak/wizard setup --integration react
13
+ ```
35
14
 
36
- ### 1. Install
15
+ The only value you may need to enter is the AllStak ingest API key. The wizard detects Vite React, CRA-style React, React Router, JavaScript, and TypeScript entry files. If the project is Next.js, use `@allstak/next` instead:
37
16
 
38
17
  ```bash
39
- npm install @allstak/react
18
+ npx @allstak/wizard setup --integration next
40
19
  ```
41
20
 
42
- ### 2. Wrap your app
21
+ ## 2. What The Wizard Changes
43
22
 
44
- ```tsx
45
- import { AllStakProvider } from '@allstak/react';
23
+ The wizard:
46
24
 
47
- export function App() {
48
- return (
49
- <AllStakProvider
50
- apiKey="ask_live_YOUR_KEY_HERE"
51
- environment="production"
52
- release="web@1.0.0"
53
- debug
54
- >
55
- <AppRoot />
56
- </AllStakProvider>
57
- );
58
- }
59
- ```
25
+ - Installs `@allstak/react`.
26
+ - Writes managed env vars to `.env.local` for Vite or `.env` for non-Vite React.
27
+ - Detects `src/main.tsx`, `src/main.jsx`, `src/index.tsx`, or `src/index.jsx`.
28
+ - Wraps the existing render tree with `AllStakProvider`.
29
+ - Preserves `React.StrictMode`, React Router, and existing providers.
30
+ - Enables provider-managed component error boundary capture.
31
+ - Wires Vite source-map upload hooks when a Vite config is present.
32
+ - Prints the changed files.
33
+ - Supports dry-run, repair, idempotent re-runs, and uninstall.
60
34
 
61
- ### 3. Trigger a test error
35
+ ## 3. Verification
62
36
 
63
- ```tsx
64
- import { AllStak } from '@allstak/react';
37
+ After setup:
65
38
 
66
- // On a button press or on mount:
67
- AllStak.captureException(new Error('test: hello from allstak-react'));
39
+ ```bash
40
+ npm run build
41
+ npx @allstak/wizard doctor --integration react
68
42
  ```
69
43
 
70
- ### 4. Check your dashboard
71
-
72
- Open [app.allstak.sa](https://app.allstak.sa) — the error appears within seconds.
73
-
74
- When `debug` is enabled you'll see `[AllStak] Initialized — session <id>` and `[AllStak] Navigation auto-instrumentation enabled` in your browser console.
75
-
76
- `AllStakProvider` handles everything:
77
- - Initializes the SDK
78
- - Wraps your app in an `AllStakErrorBoundary`
79
- - Hooks `window.onerror`, `unhandledrejection`, `console.*`, `fetch`, `history.*`
80
- - Starts Web Vitals collection
81
- - Tags every event with `platform: 'browser'`, sdk name + version
82
-
83
- ## Automatic Capture Matrix
84
-
85
- Status legend:
86
- - ✅ **Auto by default** — works the moment the provider mounts
87
- - ⚙️ **Auto when enabled by config** — set the listed prop
88
- - 🛠 **Manual only** — call the listed function yourself
89
- - 🟡 **Implemented but not browser-verified end-to-end yet**
90
- - ❌ **Not supported yet** (roadmap)
91
-
92
- | Capability | Status | Config / API | Wire form |
93
- |---|---|---|---|
94
- | Render errors via `<AllStakProvider>` boundary | ✅ | always-on inside the provider | `POST /ingest/v1/errors` with `metadata.source = 'AllStakProvider.ErrorBoundary'` + `componentStack` |
95
- | `window.onerror` global handler | ✅ | `autoCaptureBrowserErrors` (default `true`) | `POST /ingest/v1/errors` with `metadata.source = 'window.onerror'` |
96
- | `window.unhandledrejection` | ✅ | `autoCaptureBrowserErrors` | `POST /ingest/v1/errors` with `metadata.source = 'window.unhandledrejection'` |
97
- | Manual `AllStak.captureException` | 🛠 | `AllStak.captureException(err, ctx?)` | `POST /ingest/v1/errors` |
98
- | Manual `AllStak.captureMessage` | 🛠 | `AllStak.captureMessage(msg, level)` | `/ingest/v1/logs` (`info`/`warn`); both `errors` + `logs` for `error`/`fatal` |
99
- | `console.warn` / `console.error` | ✅ | `autoBreadcrumbsConsole` (default `true`); per-method via `captureConsole={ warn: true, error: true }` | `breadcrumb` of `type: 'log'`, `level: 'warn'` / `'error'`, `data.category: 'console'` |
100
- | `console.log` / `console.info` | ⚙️ | `captureConsole={{ log: true, info: true }}` (default `false` to avoid spam) | `breadcrumb` of `type: 'log'`, `level: 'info'`, `data.method: 'log'` / `'info'` |
101
- | HTTP `fetch` breadcrumbs (success) | ✅ | `autoBreadcrumbsFetch` (default `true`) | `breadcrumb` of `type: 'http'`, `level: 'info'` |
102
- | HTTP `fetch` 4xx / 5xx breadcrumbs | ✅ | `autoBreadcrumbsFetch` | `breadcrumb` of `type: 'http'`, `level: 'error'` when status ≥ 400 |
103
- | HTTP `fetch` network failure | ✅ | `autoBreadcrumbsFetch` | `breadcrumb` with `data.error`; original error rethrown |
104
- | HTTP `XMLHttpRequest` breadcrumbs | ✅ | `enableHttpTracking` (also covers fetch full events) | breadcrumb same shape |
105
- | Full HTTP request events (method / URL / headers / body) | ⚙️ | `enableHttpTracking: true` (default `false`); `httpTracking: { ... }` for redaction control | `POST /ingest/v1/http-requests` |
106
- | Recent failed HTTP attached to next exception | ⚙️ | `enableHttpTracking: true` | `metadata['http.recentFailed']` (last 5 failed requests) |
107
- | Auto navigation breadcrumbs (pushState / popstate) | ✅ | `autoBreadcrumbsNavigation` (default `true`) | `breadcrumb` of `type: 'navigation'`, `data.from`/`data.to` |
108
- | React Router integration | 🛠 | `instrumentReactRouter(useLocation())` in a `useEffect` | same shape |
109
- | Next.js Pages Router | 🛠 | `instrumentNextRouter(url)` from `Router.events.on('routeChangeComplete')` | same shape |
110
- | **Web Vitals (CLS / LCP / INP / FCP / TTFB)** | ✅ | `autoWebVitals` (default `true`) | `POST /ingest/v1/logs` with `metadata.category = 'web-vital'`, `metadata.name`, `metadata.value` |
111
- | User context | 🛠 | `AllStak.setUser({ id, email })` | `payload.user` |
112
- | Custom tags / extras / contexts | 🛠 | `AllStak.setTag` / `setExtra` / `setContext` | `payload.metadata.<key>` |
113
- | `release`, `environment`, `dist` | 🛠 via init | `<AllStakProvider release="web@1.0.0">` etc. | top-level fields on every payload |
114
- | Source maps | 🛠 build-time | `@allstak/js/sourcemaps` plugin (Vite / Webpack / Next) | injected `debugId` per chunk |
115
- | Session replay (DOM-mutation) | ⚙️ | `replay={ sampleRate: 0.1, maskAllInputs: true }` (default OFF) | `POST /ingest/v1/replay` |
116
- | Offline event queue (in-memory only — see roadmap) | ✅ | n/a; configured via transport (max 100 in-RAM, drops oldest) | retried on next successful send; lost on page navigation |
117
-
118
- ### Roadmap
119
-
120
- - Persistent offline queue (currently RAM-only; lost on page navigation)
121
- - React Query / SWR breadcrumbs
122
- - Vue / Svelte / Solid sister packages
123
-
124
- ## Verification status
125
-
126
- The capabilities marked ✅ in the matrix above were verified live in
127
- Chrome against the SDK's own wire format (see
128
- [docs/reports/react-sdk-production-readiness.md](docs/reports/react-sdk-production-readiness.md)
129
- for command-by-command details). 156 error events, 84 logs (including
130
- 5 web vitals), 9 full HTTP events, and a working render-error → fallback
131
- → resetError → recovery cycle were all observed end-to-end.
132
-
133
- The live-backend round-trip is documented in the report. The wire format
134
- is identical to `@allstak/react-native`, which was fully round-trip
135
- verified against the same backend in
136
- `../../allstak-react-native/docs/reports/react-native-backend-ingestion-verification.md`.
137
-
138
- ## Manual setup (advanced)
139
-
140
- If you need full control over initialization order, you can skip
141
- `AllStakProvider` and set up manually:
44
+ With live credentials, send a test event from your app:
142
45
 
143
46
  ```ts
144
- import { AllStak, AllStakErrorBoundary } from '@allstak/react';
47
+ import { AllStak } from '@allstak/react';
145
48
 
146
- AllStak.init({
147
- apiKey: 'ask_live_…',
148
- environment: 'production',
49
+ AllStak.captureMessage('AllStak React setup verification', {
50
+ source: 'manual-verification',
149
51
  });
150
-
151
- AllStak.captureException(new Error('test'));
152
-
153
- export function App() {
154
- return (
155
- <AllStakErrorBoundary fallback={<p>Something went wrong.</p>}>
156
- <Routes />
157
- </AllStakErrorBoundary>
158
- );
159
- }
160
52
  ```
161
53
 
162
- ## Get Your API Key
54
+ Dashboard appearance is not guaranteed by local tests. Confirm the event in AllStak before claiming live certification.
163
55
 
164
- 1. Sign up at [app.allstak.sa](https://app.allstak.sa)
165
- 2. Create a project
166
- 3. Copy your API key from **Project Settings → API Keys**
167
- 4. Export it as `ALLSTAK_API_KEY` or pass it to `AllStak.init(...)`
56
+ ## 4. Rollback / Uninstall
168
57
 
169
- ## Configuration
58
+ ```bash
59
+ npx @allstak/wizard uninstall --integration react
60
+ ```
170
61
 
171
- | Option | Type | Required | Default | Description |
172
- |---|---|---|---|---|
173
- | `apiKey` | `string` | yes | — | Project API key (`ask_live_…`) |
174
- | `environment` | `string` | no | — | Deployment env |
175
- | `release` | `string` | no | — | Version or git SHA |
176
- | `host` | `string` | no | `https://api.allstak.sa` | Ingest host override |
177
- | `user` | `{ id?, email? }` | no | — | Default user context |
178
- | `tags` | `Record<string,string>` | no | — | Default tags |
62
+ Uninstall removes wizard-managed env blocks, source-map config, imports, and provider wrappers. User-owned code outside wizard markers is preserved.
179
63
 
180
- ## Example Usage
64
+ ## 5. Manual Setup Fallback
181
65
 
182
- Capture an error inside a component:
66
+ Use manual setup only when the wizard cannot safely patch a custom entry file:
67
+
68
+ ```bash
69
+ npm install @allstak/react
70
+ ```
183
71
 
184
72
  ```tsx
185
- import { useAllStak } from '@allstak/react';
73
+ import { AllStakProvider } from '@allstak/react';
186
74
 
187
- function CheckoutButton() {
188
- const allstak = useAllStak();
75
+ export function Root({ children }: { children: React.ReactNode }) {
189
76
  return (
190
- <button onClick={() => {
191
- try { checkout(); }
192
- catch (e) { allstak.captureException(e as Error); }
193
- }}>Pay</button>
77
+ <AllStakProvider
78
+ apiKey={import.meta.env.VITE_ALLSTAK_API_KEY}
79
+ host={import.meta.env.VITE_ALLSTAK_HOST}
80
+ environment={import.meta.env.VITE_ALLSTAK_ENVIRONMENT ?? 'production'}
81
+ release={import.meta.env.VITE_ALLSTAK_RELEASE}
82
+ enableHttpTracking
83
+ >
84
+ {children}
85
+ </AllStakProvider>
194
86
  );
195
87
  }
196
88
  ```
197
89
 
198
- Wrap a component with the profiler:
199
-
200
- ```tsx
201
- import { withAllStakProfiler } from '@allstak/react';
202
- export default withAllStakProfiler(Dashboard, 'Dashboard');
203
- ```
204
-
205
- Set user context on login:
206
-
207
- ```tsx
208
- import { AllStak } from '@allstak/react';
209
- AllStak.setUser({ id: user.id, email: user.email });
210
- ```
211
-
212
- ## HTTP tracking
213
-
214
- Setting `enableHttpTracking: true` (off by default) auto-wraps `fetch`,
215
- `XMLHttpRequest`, and `axios` (when installed) so every outbound HTTP
216
- call is recorded as an `http_request` event.
217
-
218
- **Privacy defaults are aggressive:**
219
-
220
- - request/response bodies are **not** captured
221
- - headers are **not** captured
222
- - `Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, `X-Auth-Token`,
223
- `Proxy-Authorization` are **always** redacted
224
- - query params named `token`, `password`, `api_key`, `apikey`,
225
- `authorization`, `auth`, `secret`, `access_token`, `refresh_token`,
226
- `session`, `sessionid`, `jwt` are **always** redacted in the URL
227
-
228
- To enable richer capture (only on routes you control):
90
+ For manual capture:
229
91
 
230
92
  ```ts
231
- AllStak.init({
232
- apiKey: '...',
233
- enableHttpTracking: true,
234
- httpTracking: {
235
- captureRequestBody: true,
236
- captureResponseBody: true,
237
- captureHeaders: true, // auth headers still hard-redacted
238
- redactHeaders: ['x-tenant'],
239
- redactQueryParams: ['custom_id'],
240
- ignoredUrls: [/health/i, '/metrics'],
241
- allowedUrls: [],
242
- maxBodyBytes: 4096,
243
- },
244
- });
93
+ import { AllStak } from '@allstak/react';
245
94
 
246
- // axios with custom adapter (rare):
247
- import axios from 'axios';
248
- const api = AllStak.instrumentAxios(axios.create({ baseURL: 'https://api.example.com' }));
95
+ AllStak.captureException(new Error('checkout failed'));
96
+ AllStak.captureMessage('user opened checkout');
97
+ AllStak.setUser({ id: 'user_123' });
98
+ AllStak.addBreadcrumb({ type: 'navigation', message: 'Checkout' });
249
99
  ```
250
100
 
251
- When an exception fires after a failed request, the most recent failed
252
- HTTP requests (last 10) are automatically attached to the error
253
- metadata under `http.recentFailed` for easy triage.
101
+ ## 6. Configuration
254
102
 
255
- ## Production Endpoint
103
+ Provider props include:
256
104
 
257
- Production endpoint: `https://api.allstak.sa`. Override via `host` for self-hosted installs:
105
+ | Option | Default | Notes |
106
+ | --- | --- | --- |
107
+ | `apiKey` | required | Public browser ingest key. |
108
+ | `host` | `https://api.allstak.sa` | Override for self-hosted ingest. |
109
+ | `environment` | `production` | Release environment tag. |
110
+ | `release` | unset | Use app version or commit SHA. |
111
+ | `debug` | `false` | Enables SDK diagnostic logs. |
112
+ | `enableHttpTracking` | `false` | Captures HTTP metadata with redaction. |
113
+ | `autoCaptureBrowserErrors` | `true` | Captures `window.onerror` and `unhandledrejection`. |
114
+ | `autoBreadcrumbsFetch` | `true` | Adds fetch/XHR breadcrumbs. |
115
+ | `autoBreadcrumbsConsole` | `true` | Captures `warn`/`error`; `log`/`info` stay off by default. |
116
+ | `beforeSend` | unset | Last-chance event scrub/drop hook. |
258
117
 
259
- ```tsx
260
- AllStak.init({ apiKey: '...', host: 'https://allstak.mycorp.com' });
261
- ```
118
+ ## 7. Privacy / PII / Redaction
262
119
 
263
- ## Source maps — automatic via build plugin
120
+ Privacy defaults are conservative:
264
121
 
265
- Production stack traces are minified. To see real function names and
266
- line numbers in the AllStak dashboard you need to upload your source
267
- maps. The build-time tooling ships **inside `@allstak/react` itself** —
268
- no extra package to install and runs **automatically** as part of
269
- your normal build via the Vite / Webpack / Next.js plugin.
122
+ - Authorization, cookie, API key, token, and secret headers are always redacted.
123
+ - Sensitive query parameters are redacted.
124
+ - Request/response bodies are disabled unless explicitly enabled.
125
+ - Console `log` and `info` breadcrumbs are off by default.
126
+ - Use `beforeSend` for app-specific PII removal.
270
127
 
271
- The plugins inject a stable `debugId` into every chunk and (when a
272
- token is present) upload the matching `.map` to the AllStak ingest. The
273
- runtime resolver in `@allstak/react` reads `globalThis._allstakDebugIds`
274
- at capture time and attaches the right debug-id to each frame, so the
275
- symbolicator picks the correct map even after long-tail caching of
276
- bundles.
128
+ Do not send passwords, payment data, national IDs, raw tokens, or raw request/response bodies unless you have verified redaction in your app.
277
129
 
278
- ### Vite
130
+ ## 8. Source Maps / Releases
131
+
132
+ For Vite, the wizard wires the AllStak source-map plugin automatically when possible. Manual fallback:
279
133
 
280
134
  ```ts
281
- // vite.config.ts
282
135
  import { defineConfig } from 'vite';
283
136
  import react from '@vitejs/plugin-react';
284
137
  import { allstakSourcemaps } from '@allstak/react/vite';
285
138
 
286
139
  export default defineConfig({
287
- build: { sourcemap: true },
288
140
  plugins: [
289
141
  react(),
290
142
  allstakSourcemaps({
291
- release: process.env.ALLSTAK_RELEASE!,
292
- token: process.env.ALLSTAK_UPLOAD_TOKEN!,
293
- dist: 'web',
294
- }),
295
- ],
296
- });
297
- ```
298
-
299
- ### Webpack
300
-
301
- ```js
302
- // webpack.config.js
303
- const { AllStakWebpackPlugin } = require('@allstak/react/webpack');
304
-
305
- module.exports = {
306
- devtool: 'source-map',
307
- plugins: [
308
- new AllStakWebpackPlugin({
309
- release: process.env.ALLSTAK_RELEASE,
310
- token: process.env.ALLSTAK_UPLOAD_TOKEN,
311
- dist: 'web',
143
+ release: process.env.VITE_ALLSTAK_RELEASE,
144
+ token: process.env.ALLSTAK_SOURCEMAP_TOKEN,
312
145
  }),
313
146
  ],
314
- };
315
- ```
316
-
317
- ### Next.js
318
-
319
- ```js
320
- // next.config.js
321
- const { withAllStak } = require('@allstak/react/next');
322
-
323
- module.exports = withAllStak(
324
- {
325
- release: process.env.ALLSTAK_RELEASE,
326
- token: process.env.ALLSTAK_UPLOAD_TOKEN,
327
- dist: 'web',
328
- },
329
- {
330
- reactStrictMode: true,
331
- // …rest of your Next config…
332
- }
333
- );
334
- ```
335
-
336
- The `withAllStak` wrapper sets `productionBrowserSourceMaps: true` for
337
- you and only attaches the plugin to the client bundle (Node-side stack
338
- traces are already symbolicated).
339
-
340
- ### Other bundlers / programmatic use
341
-
342
- ```ts
343
- import { processBuildOutput } from '@allstak/react/sourcemaps';
344
-
345
- await processBuildOutput({
346
- dir: 'dist',
347
- release: process.env.ALLSTAK_RELEASE!,
348
- token: process.env.ALLSTAK_UPLOAD_TOKEN!,
349
- dist: 'web',
350
- });
351
- ```
352
-
353
- ### What gets sent
354
-
355
- Each map is POSTed as `multipart/form-data` to
356
- `POST /api/v1/artifacts/upload` with these fields:
357
-
358
- - `debugId` — UUID injected into the bundle and the map (matching across both)
359
- - `type` — `"sourcemap"` (and `"bundle"` if `uploadBundles: true`)
360
- - `release` — your release identifier (e.g. `web@1.4.2`)
361
- - `dist` — your distribution tag (e.g. `web`)
362
- - `file` — the map content as a Blob
363
-
364
- Auth uses `X-AllStak-Upload-Token` (a project-scoped upload token, NOT
365
- the runtime API key). Generate one in **Project Settings → Upload Tokens**.
366
-
367
- ### Privacy
368
-
369
- By default the map is uploaded as-is, which includes embedded
370
- `sourcesContent`. To strip it (smaller payloads, no source code stored
371
- on AllStak's side), set `stripSources: true`:
372
-
373
- ```ts
374
- allstakSourcemaps({
375
- release: '…',
376
- token: '…',
377
- stripSources: true,
378
147
  });
379
148
  ```
380
149
 
381
- The backend rejects uploads in privacy-mode projects when the map still
382
- contains `sourcesContent` — the SDK side surfaces a clear error.
150
+ Use the same `release` value in the provider and source-map upload.
383
151
 
384
- ## Links
152
+ ## 9. Troubleshooting
385
153
 
386
- - Documentation: https://docs.allstak.sa
387
- - Dashboard: https://app.allstak.sa
388
- - Source: https://github.com/AllStak/allstak-react
154
+ - No events: verify `VITE_ALLSTAK_API_KEY` exists and the provider is present once.
155
+ - Duplicate events: rerun `npx @allstak/wizard doctor --integration react` and check for multiple providers.
156
+ - Next.js detected: use `@allstak/next`.
157
+ - Build fails after setup: run `npx @allstak/wizard uninstall --integration react`, then rerun with `--dry-run` and inspect the planned diff.
158
+ - Source maps missing: confirm `ALLSTAK_SOURCEMAP_TOKEN` and matching `release`.
389
159
 
390
- ## License
160
+ ## 10. Limitations
391
161
 
392
- MIT © AllStak
162
+ - Live dashboard delivery is not proven by local tests.
163
+ - Session replay is privacy-first and limited compared with full DOM replay tools.
164
+ - Edge runtimes should use framework-specific packages.
165
+ - Stable production launch requires live certification against your dashboard.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  processBuildOutput
3
- } from "./chunk-G6VPGDP6.mjs";
3
+ } from "./chunk-DURAJQ3M.mjs";
4
4
 
5
5
  // src/build/webpack.ts
6
6
  var AllStakWebpackPlugin = class {
@@ -29,4 +29,4 @@ var AllStakWebpackPlugin = class {
29
29
  export {
30
30
  AllStakWebpackPlugin
31
31
  };
32
- //# sourceMappingURL=chunk-ZY4H5AN4.mjs.map
32
+ //# sourceMappingURL=chunk-3JRNQSVX.mjs.map
@@ -155,6 +155,7 @@ async function uploadAll(pairs, opts) {
155
155
 
156
156
  // src/build/sourcemaps.ts
157
157
  import { resolve } from "path";
158
+ import { existsSync, readFileSync as readFileSync3 } from "fs";
158
159
  async function processBuildOutput(opts) {
159
160
  const dir = resolve(opts.dir);
160
161
  const pairs = findPairs(dir);
@@ -172,8 +173,11 @@ async function processBuildOutput(opts) {
172
173
  for (const i of injected) {
173
174
  log(` ${i.bundleName} ${i.debugId} ${i.reused ? "(reused)" : "(new)"}`);
174
175
  }
175
- const token = opts.token ?? process.env.ALLSTAK_UPLOAD_TOKEN;
176
- const release = opts.release ?? process.env.ALLSTAK_RELEASE;
176
+ const env = loadAllStakEnv();
177
+ const token = opts.token ?? env.ALLSTAK_UPLOAD_TOKEN;
178
+ const release = opts.release ?? env.ALLSTAK_RELEASE;
179
+ const host = opts.host ?? env.ALLSTAK_HOST;
180
+ const dist = opts.dist ?? env.ALLSTAK_DIST;
177
181
  if (opts.injectOnly || !token) {
178
182
  if (!opts.injectOnly && !token) {
179
183
  log("skipping upload \u2014 no token (set ALLSTAK_UPLOAD_TOKEN or pass `token`)");
@@ -187,7 +191,9 @@ async function processBuildOutput(opts) {
187
191
  const uploaded = await uploadAll(pairs, {
188
192
  ...opts,
189
193
  release,
190
- token
194
+ token,
195
+ host,
196
+ dist
191
197
  });
192
198
  for (const u of uploaded) {
193
199
  if (u.ok) {
@@ -199,6 +205,24 @@ async function processBuildOutput(opts) {
199
205
  }
200
206
  return { dir, pairs: pairs.length, injected, uploaded };
201
207
  }
208
+ function loadAllStakEnv() {
209
+ const out = { ...process.env };
210
+ for (const file of [".env.local", ".env"]) {
211
+ const full = resolve(process.cwd(), file);
212
+ if (!existsSync(full)) continue;
213
+ const text = readFileSync3(full, "utf8");
214
+ for (const line of text.split(/\r?\n/)) {
215
+ const trimmed = line.trim();
216
+ if (!trimmed || trimmed.startsWith("#")) continue;
217
+ const match = /^([A-Z0-9_]+)\s*=\s*(.*)$/.exec(trimmed);
218
+ if (!match) continue;
219
+ const key = match[1];
220
+ if (out[key] !== void 0) continue;
221
+ out[key] = match[2].replace(/^['"]|['"]$/g, "");
222
+ }
223
+ }
224
+ return out;
225
+ }
202
226
 
203
227
  export {
204
228
  walk,
@@ -211,4 +235,4 @@ export {
211
235
  uploadAll,
212
236
  processBuildOutput
213
237
  };
214
- //# sourceMappingURL=chunk-G6VPGDP6.mjs.map
238
+ //# sourceMappingURL=chunk-DURAJQ3M.mjs.map