@radhya/mach 2.4.4 → 2.6.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.
@@ -165,6 +165,21 @@ export default {
165
165
  }
166
166
  ```
167
167
 
168
+ ## Flutter Projects
169
+
170
+ For Flutter applications, setup makes conservative, idempotent native changes:
171
+
172
+ - adds verified HTTPS App Links and the custom URI scheme to the launcher activity;
173
+ - adds `applinks:<domain>` to the Runner entitlements;
174
+ - connects `CODE_SIGN_ENTITLEMENTS` when the Runner target can be identified;
175
+ - adds the custom URI scheme to `Info.plist`.
176
+
177
+ Mach does not choose the application's Dart router. Handle the incoming URI in
178
+ the routing package already used by the app (for example `go_router` or
179
+ `app_links`). `mach deeplink verify` checks the Android manifest, associated
180
+ domain, Xcode entitlement connection, generated association files, and optional
181
+ live endpoints.
182
+
168
183
  ## Verify
169
184
 
170
185
  Verify local files:
@@ -191,6 +206,9 @@ Live verification checks:
191
206
  - `https://<domain>/apple-app-site-association`
192
207
  - `https://<domain>/.well-known/assetlinks.json`
193
208
 
194
- ## Current Scope
209
+ ## Safety
195
210
 
196
- The first implementation generates hosted files and Expo integration. Vanilla React Native native file patching is intentionally conservative in this phase: verification reports missing Android manifest or iOS entitlement entries, but setup does not mutate native XML or Xcode project files yet.
211
+ Expo configuration uses its plugin contract. Flutter native edits are applied
212
+ only when Mach can identify standard launcher/Runner structures. Vanilla React
213
+ Native verification remains conservative and reports native gaps rather than
214
+ rewriting an unfamiliar project.
@@ -1,6 +1,9 @@
1
1
  # Framework Guides
2
2
 
3
- Mach uses `mach.config.json` as the source of truth for framework behavior. Builds do not infer framework from `package.json`, because package scanning is fragile in real projects and can make Expo, bare React Native, and future Flutter support affect each other accidentally.
3
+ Mach uses `mach.config.json` as the source of truth for framework behavior.
4
+ Builds do not infer framework at execution time because package or workspace
5
+ scanning is fragile and can make Expo, bare React Native, and Flutter pipelines
6
+ affect each other accidentally.
4
7
 
5
8
  ## Choose Your Framework
6
9
 
@@ -10,7 +13,7 @@ Mach uses `mach.config.json` as the source of truth for framework behavior. Buil
10
13
  | An Expo app that should run `expo prebuild` during cloud builds | `"expo"` | [Expo](expo.md) |
11
14
  | A Flutter app | `"flutter"` | [Flutter](flutter.md) |
12
15
 
13
- `mach init` and `mach link` create:
16
+ `mach init` and `mach link` detect the selected application and create:
14
17
 
15
18
  ```json
16
19
  {
@@ -18,7 +21,8 @@ Mach uses `mach.config.json` as the source of truth for framework behavior. Buil
18
21
  }
19
22
  ```
20
23
 
21
- Change this to `"expo"` before building an Expo project. Flutter is accepted in config for forward compatibility, but Flutter builds intentionally fail until the Flutter builder is implemented.
24
+ The value is `"flutter"` for a Flutter app and `"expo"` for an Expo app. Builds
25
+ still use this explicit saved value; detection is only an initialization aid.
22
26
 
23
27
  ## Why This Is Explicit
24
28
 
@@ -26,7 +30,7 @@ The same repository can contain Expo packages, React Native native folders, cust
26
30
 
27
31
  - React Native builds never run Expo prebuild.
28
32
  - Expo builds keep the existing Expo prebuild and dev-client behavior.
29
- - Flutter can be added later without changing `mach build` commands.
33
+ - Flutter runs its Dart/native pipeline without entering JavaScript tooling.
30
34
  - Documentation, CI, and support conversations can point to one clear setting.
31
35
 
32
36
  ## Required Config
@@ -61,10 +65,10 @@ repository root and set an explicit app directory:
61
65
  }
62
66
  ```
63
67
 
64
- Use the same `appDirectory` with `"react-native"` for a bare React Native app.
65
- Mach installs workspace dependencies from the repository root and runs
66
- framework-native commands from the selected app. If `appDirectory` is omitted,
67
- it defaults to `"."`, preserving existing root-level behavior.
68
+ Use the same `appDirectory` with `"react-native"` for bare React Native or
69
+ `"flutter"` for an application in a Dart pub workspace. Mach resolves workspace
70
+ dependencies and runs framework-native commands from the selected app. If
71
+ `appDirectory` is omitted, it defaults to `"."`, preserving existing behavior.
68
72
 
69
73
  Aliases such as `reactnative` and `react_native` are normalized to `react-native`, but new projects should use the canonical `react-native` value.
70
74
 
@@ -85,6 +89,6 @@ Framework selection only changes what happens inside the build runner.
85
89
 
86
90
  ## Failure Messages
87
91
 
88
- If `framework` is missing, Mach stops before queuing the build and asks you to add one of the allowed values. If `framework` is invalid, Mach stops before upload and prints the accepted values. If `framework` is `flutter`, Mach currently stops with a clear "Flutter builds are not implemented yet" message.
92
+ If `framework` is missing, Mach stops before queuing the build and asks you to add one of the allowed values. If `framework` is invalid, Mach stops before upload and prints the accepted values. Framework-specific commands validate their capability before changing the project.
89
93
 
90
94
  This is intentional. A build should fail early and clearly instead of silently running the wrong native pipeline.
@@ -1,16 +1,21 @@
1
1
  # Flutter Builds
2
2
 
3
- Flutter is reserved in Mach configuration so the CLI can support it without changing user-facing commands later.
3
+ Mach builds standalone Flutter applications on Android, iOS, and web while keeping
4
+ the same build, credential, submission, versioning, and dashboard workflow used
5
+ by React Native and Expo projects.
4
6
 
5
- ## Current Status
7
+ ## Initialize or link
6
8
 
7
- `framework: "flutter"` is recognized as a valid config value, but Flutter cloud builders are not implemented yet. If you run a build with Flutter selected, Mach fails with a clear message instead of trying to run the React Native or Expo pipeline.
8
-
9
- ## Planned Config Shape
9
+ Run `mach init` in a Flutter application or at a Dart workspace root. Mach
10
+ detects the app, writes `framework: "flutter"`, stores `appDirectory`, and pins
11
+ the installed stable Flutter SDK for repeatable managed builds. `mach link`
12
+ preserves every existing build profile and custom field.
10
13
 
11
14
  ```json
12
15
  {
13
16
  "framework": "flutter",
17
+ "appDirectory": ".",
18
+ "flutter": { "sdkVersion": "3.35.2" },
14
19
  "ios": {
15
20
  "bundleIdentifier": "com.example.app",
16
21
  "buildNumber": "auto"
@@ -18,50 +23,133 @@ Flutter is reserved in Mach configuration so the CLI can support it without chan
18
23
  "android": {
19
24
  "package": "com.example.app",
20
25
  "versionCode": "auto"
26
+ },
27
+ "build": {
28
+ "qa-blue": {
29
+ "environment": "qa",
30
+ "distribution": "internal",
31
+ "flutter": {
32
+ "flavor": "staging",
33
+ "target": "lib/main_staging.dart",
34
+ "mode": "release",
35
+ "dartDefinesFromEnv": ["API_URL", "APP_ENV"]
36
+ }
37
+ },
38
+ "customer-release": {
39
+ "environment": "production",
40
+ "distribution": "store",
41
+ "android": { "package": "com.example.app" },
42
+ "ios": { "bundleIdentifier": "com.example.app" },
43
+ "flutter": {
44
+ "flavor": "production",
45
+ "target": "lib/main_production.dart",
46
+ "obfuscate": true,
47
+ "splitDebugInfo": true
48
+ }
49
+ }
21
50
  }
22
51
  }
23
52
  ```
24
53
 
25
- ## Planned Behavior
54
+ Profile names are labels. They may be any unique strings, and Mach does not
55
+ limit how many profiles exist. `environment`, `distribution`, platform fields,
56
+ and the nested `flutter` object determine the build behavior.
57
+
58
+ ## Flutter profile fields
26
59
 
27
- The Flutter builder should be separate from the React Native and Expo builders:
60
+ | Field | Purpose |
61
+ | --- | --- |
62
+ | `flavor` | Android product flavor and shared iOS scheme. Omit for unflavored apps. |
63
+ | `target` | Dart entrypoint relative to `appDirectory`; defaults to `lib/main.dart`. |
64
+ | `mode` | `debug`, `profile`, or `release`. Store/internal builds default to release. |
65
+ | `dartDefinesFromEnv` | Names of selected environment values compiled with `--dart-define`. |
66
+ | `obfuscate` | Obfuscates Android/iOS release Dart code and automatically preserves split debug symbols. |
67
+ | `splitDebugInfo` | Preserves split debug symbols for Android/iOS releases even without obfuscation. |
28
68
 
29
- - Android should run Flutter/Gradle commands from the Flutter project.
30
- - iOS should run Flutter build/archive commands and then the same managed signing/upload flow.
31
- - Expo prebuild and React Native Metro cache handling should not run for Flutter.
32
- - Store submission should keep using the same `mach submit` command surface.
69
+ These fields normally apply to both platforms. Put a nested `flutter` object
70
+ under `android` or `ios` when native flavor/scheme names differ; platform fields
71
+ override the shared values. For example, `android.flutter.flavor` can select an
72
+ Android-only product flavor without requiring a matching Xcode scheme.
33
73
 
34
- Until that builder exists, use `react-native` or `expo`.
74
+ Values named in `dartDefinesFromEnv` must exist in the resolved Mach environment.
75
+ They are compiled into the application and therefore must not be treated as
76
+ secrets. Mach stores only their names in build configuration, never the values.
35
77
 
36
- ## Why It Is Already In Config
78
+ Flutter's `default-flavor` in `pubspec.yaml` is honored when a profile does not
79
+ set a flavor. For iOS flavors, Mach selects the shared scheme and matching
80
+ `Debug-<flavor>`, `Profile-<flavor>`, or `Release-<flavor>` configuration. Set
81
+ `build.<profile>.ios.iosConfiguration` explicitly for a nonstandard Xcode setup.
82
+ For Android projects that declare product flavors without a default, Mach stops
83
+ before allocating a cloud runner and identifies the missing profile field.
37
84
 
38
- Mach accepts `flutter` now so projects, Dashboard records, and docs can move toward a framework-neutral model before Flutter execution is enabled. This avoids another command change later. The command remains:
85
+ ## Commands
39
86
 
40
87
  ```bash
41
- mach build --platform ios --profile production
42
- mach build --platform android --profile production
88
+ mach start --profile qa-blue
89
+ mach build --platform android --profile qa-blue
90
+ mach build --platform ios --profile customer-release
91
+ mach build --platform web --profile customer-release
92
+ mach audit
93
+ mach credentials
94
+ mach submit --latest --platform android --profile customer-release
95
+ mach submit --latest --platform ios --profile customer-release
43
96
  ```
44
97
 
45
- Only the internal build runner changes once Flutter is implemented.
98
+ Android store builds produce AAB files; internal/development builds produce APK
99
+ files by default. Set `apk: true` or `apk: false` explicitly on any profile to
100
+ choose APK or AAB. iOS reuses Mach's
101
+ managed certificate, provisioning-profile, archive, validation, and submission
102
+ pipeline. Automatic version counters become Flutter `--build-number` values and
103
+ are verified in the final APK/AAB/IPA.
46
104
 
47
- ## Current Failure Mode
105
+ Web builds run `flutter build web` on the managed Linux runner and produce a
106
+ downloadable `flutter-web.zip`. A Flutter `web/` directory is required. Web is
107
+ not a store-submission or Maestro target, and it does not accept mobile-only
108
+ obfuscation/split-debug-info flags.
48
109
 
49
- If you run a build today with:
110
+ For Android/iOS release hardening, configure `flutter.obfuscate` or pass
111
+ `--flutter-obfuscate`. Mach stores symbols outside the packaged app and exposes
112
+ `flutter-symbols.zip` with the build artifacts so crash stacks can be decoded.
50
113
 
51
- ```json
52
- {
53
- "framework": "flutter"
54
- }
55
- ```
114
+ ## Managed runner behavior
115
+
116
+ - The exact configured Flutter SDK is activated or resolved from Flutter's
117
+ official archive manifest, downloaded, and SHA-256 verified.
118
+ - Pub, Gradle, CocoaPods, and Xcode caches are isolated by project/framework/SDK.
119
+ - Metro, Expo prebuild, Node dependency installation, and React Native cache
120
+ cleanup never run for Flutter.
121
+ - Android signing material is written only to a temporary keystore and removed.
122
+ - iOS signing material remains in Mach's temporary-keychain workflow.
123
+ - `preBuild` and `postBuild` remain available to every profile.
56
124
 
57
- Mach stops before starting the React Native or Expo build pipeline and prints that Flutter builds are not implemented yet. This is safer than trying to run Gradle or Xcode with React Native assumptions.
125
+ `mach audit` checks the SDK pin, Dart constraint, `flutter doctor`, static
126
+ analysis, dependency advisories/freshness, native permissions, Android manifest,
127
+ iOS ATS, source secrets, insecure storage, debug prints, and delivery impact.
58
128
 
59
- ## Implementation Checklist
129
+ ## Delivery services
60
130
 
61
- When Flutter support is added, keep it isolated:
131
+ ```bash
132
+ mach push setup --profile <profile>
133
+ mach deeplink setup
134
+ mach deeplink verify
135
+ mach ota setup --profile <profile>
136
+ mach ota release --platform all --profile <profile>
137
+ mach ota publish --platform all --profile <profile> --track <track>
138
+ ```
62
139
 
63
- - Add Flutter-specific Android and iOS build runners.
64
- - Keep Expo prebuild logic out of Flutter.
65
- - Keep React Native Metro and bundling assumptions out of Flutter.
66
- - Reuse Mach credentials, signing, artifact upload, build pages, and submission flows.
67
- - Keep `mach build`, `mach submit`, and Dashboard UX unchanged.
140
+ Push setup installs `mach_push_flutter`, creates an application-owned callback
141
+ file, starts registration without blocking `runApp`, and wires APNs/Firebase
142
+ native configuration. It follows `appDirectory` and wires every distinct Dart
143
+ entrypoint selected by the profile's shared, Android, or iOS Flutter settings.
144
+ Profile names are never special: use any name defined under `build.profiles`.
145
+ Deep-link setup patches Android App Links, iOS Associated
146
+ Domains, and the custom URI scheme idempotently. Flutter OTA delegates to the
147
+ customer's Shorebird account; Mach never stores the provider token.
148
+
149
+ ## Current scope
150
+
151
+ Mach supports standalone Flutter apps, including Dart workspaces with an
152
+ explicit `appDirectory`. Flutter add-to-app modules remain intentionally out of
153
+ scope because their host application requires a different build contract.
154
+ `mach sitemap` remains Expo Router-specific and fails early for Flutter. Flutter
155
+ web is a build artifact workflow; Mach does not host the generated website.
package/docs/ota.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mach OTA Updates
2
2
 
3
- Mach OTA publishes JavaScript bundles and assets through Mach API and Mach-managed object storage. It does not publish releases to EAS Update, and mobile apps never receive storage credentials.
3
+ Mach OTA selects a safe provider by framework. Expo and bare React Native publish JavaScript/assets through Mach-managed storage. Flutter delegates Dart code push directly to the customer's Shorebird account, and Mach never receives or stores the Shorebird token.
4
4
 
5
5
  ## Supported apps
6
6
 
@@ -10,9 +10,35 @@ Mach currently uses the open-source `expo-updates` runtime for both supported Re
10
10
  | --- | --- | --- |
11
11
  | `expo` | Expo prebuild/CNG | Installs `expo-updates` and applies `@radhya/mach/expo-plugin` during prebuild. |
12
12
  | `react-native` | Committed `ios/` and `android/` projects | Installs Expo Modules when needed, installs `expo-updates`, and synchronizes its native configuration without running prebuild. |
13
+ | `flutter` | Flutter Android/iOS applications | Initializes and orchestrates Shorebird using the customer-owned account and `SHOREBIRD_TOKEN` from the local/CI environment. |
13
14
 
14
15
  `mach-react-native` is reserved for a future Mach-owned client and is not a supported engine yet.
15
16
 
17
+ ## Flutter with Shorebird
18
+
19
+ ```bash
20
+ mach ota setup --profile staging
21
+ mach ota verify --profile staging
22
+ mach ota release --platform all --profile staging
23
+ mach ota publish --platform all --profile staging --track staging --release-version latest
24
+ mach ota list --release-version 1.2.0+42
25
+ mach ota promote --release-version 1.2.0+42 --patch-number 1
26
+ mach ota rollback --release-version 1.2.0+42 --patch-number 2
27
+ ```
28
+
29
+ Setup runs `shorebird init` when needed and stores only `enabled`,
30
+ `engine: "shorebird"`, and the default track in `mach.config.json`. It never
31
+ writes `SHOREBIRD_TOKEN`; interactive machines can use an existing Shorebird
32
+ login, while CI should create an API key in Shorebird Console → Account → API
33
+ Keys and provide it through the secret store. Release
34
+ commands pin `flutter.sdkVersion` and reuse each profile's flavor, target, and
35
+ selected `dartDefinesFromEnv`. Patch commands target the exact Shorebird release
36
+ and can publish to `staging` before promotion to `stable`.
37
+
38
+ Shorebird patches cannot safely carry native configuration changes or newly
39
+ declared assets. Make a new `mach ota release` and store submission for those
40
+ changes. Flutter web does not use mobile OTA.
41
+
16
42
  ## Initial setup
17
43
 
18
44
  Run setup from the project root:
@@ -22,7 +48,7 @@ mach ota setup
22
48
  mach ota verify
23
49
  ```
24
50
 
25
- Setup reads project ID, framework, channel, runtime policy, and existing URL from `mach.config.json`. Command flags have higher precedence. It also refreshes an older project-local `@radhya/mach` package so Expo prebuild uses a plugin compatible with the running CLI. Interactive setup asks before installing dependencies; use `mach --yes ota setup` in automation. Use `--skip-install` only when dependencies are managed separately.
51
+ For Expo/React Native, setup reads project ID, framework, channel, runtime policy, and existing URL from `mach.config.json`. Command flags have higher precedence. It also refreshes an older project-local `@radhya/mach` package so Expo prebuild uses a plugin compatible with the running CLI. Interactive setup asks before installing dependencies; use `mach --yes ota setup` in automation. Use `--skip-install` only when dependencies are managed separately.
26
52
 
27
53
  For a bare React Native project, setup may make these intentional changes:
28
54
 
package/docs/push.md CHANGED
@@ -13,7 +13,7 @@ mach link
13
13
  mach push setup
14
14
  ```
15
15
 
16
- `push setup` detects Expo or bare React Native; reads the native app
16
+ `push setup` detects Flutter, Expo, or bare React Native; reads the native app
17
17
  identifiers; creates or reuses the matching MACH Push app; installs the mobile
18
18
  SDK; and starts permission, registration, and notification listeners from the
19
19
  application entry point.
@@ -35,6 +35,17 @@ the APNs entitlement, Android notification permission, Firebase config path,
35
35
  and public MACH Push configuration during prebuild. Expo Go cannot load custom
36
36
  native modules, so create a new development or production build after setup.
37
37
 
38
+ Flutter setup installs `mach_push_flutter`, writes generated public config to
39
+ `lib/mach_push.generated.dart`, and creates `lib/mach_push.dart` for callbacks.
40
+ The callback file belongs to the application and is never overwritten. Mach
41
+ imports it and adds one non-blocking startup call to the selected `main*.dart`
42
+ entrypoint, re-registers rotated provider tokens, and applies the same APNs and
43
+ Firebase native wiring used by bare React Native. If a custom entrypoint cannot
44
+ be patched safely, setup prints the single startup call to add manually.
45
+ Use `mach push setup --profile <profile>` when Flutter targets differ by build
46
+ profile. Mach follows `appDirectory` and wires all distinct shared, Android,
47
+ and iOS entrypoints selected by that profile; the profile may have any name.
48
+
38
49
  Use `mach push init` only when you intentionally want to create the server-side
39
50
  push app without installing or wiring a mobile SDK.
40
51
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@radhya/mach",
3
- "version": "2.4.4",
4
- "description": "Mach CLI: Cloud Build Orchestrator for React Native & Expo",
3
+ "version": "2.6.0",
4
+ "description": "Mach CLI: cloud build and delivery for Flutter, React Native, and Expo",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "build": "tsup src/index.ts src/commands/isolated-upload.ts --format esm --clean --minify --dts",
20
- "test": "npm run typecheck:ota && tsx --test src/**/*.test.ts && node --test tests/*.test.cjs",
20
+ "test": "npm run typecheck:ota && node --import tsx --test \"src/**/*.test.ts\" && node --test tests/*.test.cjs",
21
21
  "typecheck:ota": "tsc --noEmit --skipLibCheck --moduleResolution Bundler --module ESNext --target ES2022 --esModuleInterop --noImplicitAny false src/commands/ota.ts",
22
22
  "start": "node dist/index.js",
23
23
  "dev": "tsx src/index.ts",
@@ -29,6 +29,7 @@
29
29
  "keywords": [
30
30
  "react-native",
31
31
  "expo",
32
+ "flutter",
32
33
  "build",
33
34
  "cloud",
34
35
  "ios",
@@ -1,4 +0,0 @@
1
- var o={name:"Mach",nameLower:"mach",nameUpper:"MACH",company:"Radhya Softlabs",npmScope:"@radhya",configFileName:"mach.config.json",configDir:".mach",workspacesDir:".mach-workspaces",remoteWorkspacesDir:"mach_workspaces",envPrefix:"MACH_",bucketPrefix:"skye-builds-385229479322",buildPrefix:"mach-build",credentialsKeychain:"mach-credentials.keychain",keychainPassword:"mach",cliTag:e=>` Mach CLI - ${e} `,fastlanePrefix:"mach",jsonStartMarker:"___MACH_JSON_START___",jsonEndMarker:"___MACH_JSON_END___",prewarmedMarker:"/opt/mach-prewarmed"};import s from"fs";import f from"path";import v from"os";import T from"axios";var m=f.join(v.homedir(),o.configDir),d=f.join(m,"credentials.json");function h(){return process.env[`${o.envPrefix}TOKEN`]?.trim()||void 0}function g(e){s.existsSync(m)||s.mkdirSync(m,{recursive:!0}),s.writeFileSync(d,JSON.stringify(e,null,2))}function l(){let e=h();if(e)return{token:e,email:"token-auth"};if(!s.existsSync(d))return null;try{return JSON.parse(s.readFileSync(d,"utf-8"))}catch{return null}}function I(){return s.existsSync(d)?(s.unlinkSync(d),!0):!1}function $(){let e=h();if(e)return{token:e,email:"token-auth"};let r=l();if(r?.token)return r;console.error(`\x1B[31mAuthentication required.\x1B[0m Either:
2
- 1. Run \x1B[33m${o.nameLower} login\x1B[0m for interactive login
3
- 2. Set \x1B[33m${o.envPrefix}TOKEN\x1B[0m environment variable for CI/CD`),process.exit(1)}async function k(e){let r=l();if(!r||!r.refreshToken)return null;try{let t=await T.post(`${e}/refresh-token`,{username:r.email,refreshToken:r.refreshToken});if(t.data.status==="success"&&t.data.user){let n={...r,id:t.data.user.id||r.id,token:t.data.user.token,refreshToken:t.data.user.refreshToken||r.refreshToken};return g(n),n.token}}catch{}return null}import S from"axios";import C from"dotenv";import x from"path";import{fileURLToPath as b}from"url";var _=x.dirname(b(import.meta.url));C.config({path:x.join(_,"../.env")});var c=process.env[`${o.envPrefix}API_URL`]||"https://mach-api.securejs.in",D="https://getmach.dev",A=c.includes("localhost:3001")||c.includes("127.0.0.1:3001")?c.replace("3001","8081"):D,B=process.env[`${o.envPrefix}DASHBOARD_URL`]||A;var u=S.create({baseURL:c,headers:{Connection:"close"}});u.interceptors.request.use(e=>{let t=l()?.token||process.env[`${o.envPrefix}TOKEN`];return t&&(e.headers.Authorization=`Bearer ${t}`),e},e=>Promise.reject(e));u.interceptors.response.use(e=>e,async e=>{let{config:r}=e;if((!e.response||e.code==="ECONNRESET"||e.code==="ETIMEDOUT")&&(!r._retryCount||r._retryCount<3)){r._retryCount=(r._retryCount||0)+1;let n=Math.pow(2,r._retryCount-1)*1e3;return console.warn(`\x1B[33m[NETWORK] Transient error (${e.code||"UNKNOWN"}). Retrying in ${n/1e3}s... (Attempt ${r._retryCount}/3)\x1B[0m`),await new Promise(a=>setTimeout(a,n)),u(r)}return Promise.reject(e)});u.interceptors.response.use(e=>e,async e=>{let r=e.config;if(e.response?.status===401&&!r._retry){if(r._retry=!0,process.env[`${o.envPrefix}TOKEN`])return console.error(`\x1B[31mAuthentication failed.\x1B[0m Your ${o.envPrefix}TOKEN may be invalid or expired.
4
- Generate a new token at the ${o.name} Dashboard \u2192 Settings \u2192 Access Tokens.`),Promise.reject(e);try{let n=await k(c);if(n)return r.headers.Authorization=`Bearer ${n}`,u(r)}catch(n){return Promise.reject(n)}}return Promise.reject(e)});var p=e=>String(e||"").trim().toLowerCase().replace(/_/g,"-");function y(e){let r=p(e);if(["development","dev"].includes(r))return"development";if(["adhoc","ad-hoc","internal","staging","stage","preview"].includes(r))return"adhoc";if(["store","app-store","appstore","production","prod"].includes(r))return"store"}function X(e){if(e.storedDistributionType!==e.requestedDistributionType)throw new Error(`Dashboard stored ${e.credentialType} as ${String(e.storedDistributionType||"unknown")} instead of ${e.requestedDistributionType}.`)}function Z(e){let r=y(e.requestedCredentialType);if(r)return r;let t=e.profile||{};if(t.developmentClient||t.simulator||t.ios?.simulator)return"development";let n=p(t.distribution),a=p(t.iosExportMethod||t.ios?.exportMethod),i=p(t.environment);return a==="app-store"||n==="store"?"store":a==="development"||n==="development"?"development":a==="ad-hoc"||a==="adhoc"||n==="ad-hoc"||n==="adhoc"||n==="internal"?"adhoc":i==="production"||i==="store"?"store":i==="development"||i==="dev"?"development":i==="staging"||i==="stage"||i==="preview"?"adhoc":y(e.buildProfile)||"development"}export{o as a,g as b,l as c,I as d,$ as e,c as f,B as g,u as h,y as i,X as j,Z as k};