@ship-et/buildatlas-cli 0.0.0-stage → 0.11.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/LICENSE +21 -0
- package/README.md +81 -2
- package/dist/browser-login.d.ts +12 -0
- package/dist/browser-login.d.ts.map +1 -0
- package/dist/browser-login.js +94 -0
- package/dist/browser-login.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +115 -0
- package/dist/client.js.map +1 -0
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +102 -0
- package/dist/client.test.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +88 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/build.d.ts +4 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +297 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/builds.d.ts +3 -0
- package/dist/commands/builds.d.ts.map +1 -0
- package/dist/commands/builds.js +102 -0
- package/dist/commands/builds.js.map +1 -0
- package/dist/commands/credentials-wizard.d.ts +25 -0
- package/dist/commands/credentials-wizard.d.ts.map +1 -0
- package/dist/commands/credentials-wizard.js +274 -0
- package/dist/commands/credentials-wizard.js.map +1 -0
- package/dist/commands/credentials.d.ts +3 -0
- package/dist/commands/credentials.d.ts.map +1 -0
- package/dist/commands/credentials.js +249 -0
- package/dist/commands/credentials.js.map +1 -0
- package/dist/commands/env.d.ts +37 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +220 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/expo-tokens.d.ts +3 -0
- package/dist/commands/expo-tokens.d.ts.map +1 -0
- package/dist/commands/expo-tokens.js +103 -0
- package/dist/commands/expo-tokens.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +204 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/projects.d.ts +11 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +148 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/submit.d.ts +10 -0
- package/dist/commands/submit.d.ts.map +1 -0
- package/dist/commands/submit.js +118 -0
- package/dist/commands/submit.js.map +1 -0
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +93 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/config.d.ts +66 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +255 -0
- package/dist/config.js.map +1 -0
- package/dist/detach.d.ts +18 -0
- package/dist/detach.d.ts.map +1 -0
- package/dist/detach.js +42 -0
- package/dist/detach.js.map +1 -0
- package/dist/eas-credentials-zip.d.ts +38 -0
- package/dist/eas-credentials-zip.d.ts.map +1 -0
- package/dist/eas-credentials-zip.js +63 -0
- package/dist/eas-credentials-zip.js.map +1 -0
- package/dist/eas-json.d.ts +21 -0
- package/dist/eas-json.d.ts.map +1 -0
- package/dist/eas-json.js +32 -0
- package/dist/eas-json.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/logs.d.ts +13 -0
- package/dist/logs.d.ts.map +1 -0
- package/dist/logs.js +70 -0
- package/dist/logs.js.map +1 -0
- package/dist/packaging.test.d.ts +2 -0
- package/dist/packaging.test.d.ts.map +1 -0
- package/dist/packaging.test.js +79 -0
- package/dist/packaging.test.js.map +1 -0
- package/dist/profiles.test.d.ts +2 -0
- package/dist/profiles.test.d.ts.map +1 -0
- package/dist/profiles.test.js +56 -0
- package/dist/profiles.test.js.map +1 -0
- package/dist/project-hint.d.ts +12 -0
- package/dist/project-hint.d.ts.map +1 -0
- package/dist/project-hint.js +19 -0
- package/dist/project-hint.js.map +1 -0
- package/dist/project-type.d.ts +43 -0
- package/dist/project-type.d.ts.map +1 -0
- package/dist/project-type.js +88 -0
- package/dist/project-type.js.map +1 -0
- package/dist/project-type.test.d.ts +2 -0
- package/dist/project-type.test.d.ts.map +1 -0
- package/dist/project-type.test.js +77 -0
- package/dist/project-type.test.js.map +1 -0
- package/dist/prompt.d.ts +56 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +157 -0
- package/dist/prompt.js.map +1 -0
- package/dist/tarball.d.ts +39 -0
- package/dist/tarball.d.ts.map +1 -0
- package/dist/tarball.js +208 -0
- package/dist/tarball.js.map +1 -0
- package/dist/tarball.test.d.ts +2 -0
- package/dist/tarball.test.d.ts.map +1 -0
- package/dist/tarball.test.js +97 -0
- package/dist/tarball.test.js.map +1 -0
- package/package.json +56 -4
package/dist/config.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
2
|
+
import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import pc from 'picocolors';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
const execFile = promisify(execFileCb);
|
|
9
|
+
/**
|
|
10
|
+
* The instance this CLI ships pointed at, so a first-time user does not have to type a
|
|
11
|
+
* URL. Overridden by a stored login, `--api`, or BUILDATLAS_API_URL — this is only the
|
|
12
|
+
* fallback when nothing else says otherwise. Baked at publish via BUILDATLAS_DEFAULT_API_URL
|
|
13
|
+
* for a differently-hosted build.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_API_URL = process.env.BUILDATLAS_DEFAULT_API_URL ?? 'https://buildatlas.ship.et';
|
|
16
|
+
/**
|
|
17
|
+
* Credentials live in ~/.buildatlas/auth.json at mode 0600. Env vars win over the
|
|
18
|
+
* file so CI can inject a token without writing to disk.
|
|
19
|
+
*/
|
|
20
|
+
const configSchema = z.object({
|
|
21
|
+
apiUrl: z.string().default(DEFAULT_API_URL),
|
|
22
|
+
token: z.string().optional(),
|
|
23
|
+
email: z.string().optional(),
|
|
24
|
+
});
|
|
25
|
+
export const configPath = () => join(homedir(), '.buildatlas', 'auth.json');
|
|
26
|
+
/**
|
|
27
|
+
* Where the CLI used to keep its config, back when the command was `atlas`.
|
|
28
|
+
* Read as a fallback so an existing install does not silently become logged out
|
|
29
|
+
* after an upgrade; never written to.
|
|
30
|
+
*/
|
|
31
|
+
const legacyConfigPath = () => join(homedir(), '.atlas', 'auth.json');
|
|
32
|
+
/**
|
|
33
|
+
* The API URL that was actually stored, as opposed to the localhost default.
|
|
34
|
+
*
|
|
35
|
+
* `login` needs the distinction: someone who installed this from npm and runs
|
|
36
|
+
* `buildatlas login` with no `--api` should be asked where their server is, not
|
|
37
|
+
* quietly pointed at localhost and then shown a connection error.
|
|
38
|
+
*/
|
|
39
|
+
export async function storedApiUrl() {
|
|
40
|
+
for (const path of [configPath(), legacyConfigPath()]) {
|
|
41
|
+
try {
|
|
42
|
+
const parsed = configSchema.partial().safeParse(JSON.parse(await readFile(path, 'utf8')));
|
|
43
|
+
if (parsed.success && parsed.data.apiUrl)
|
|
44
|
+
return parsed.data.apiUrl;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Missing or unreadable; the caller treats that as "not configured".
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return process.env.BUILDATLAS_API_URL ?? process.env.ATLAS_API_URL;
|
|
51
|
+
}
|
|
52
|
+
export async function loadConfig() {
|
|
53
|
+
let fromFile = {};
|
|
54
|
+
for (const path of [configPath(), legacyConfigPath()]) {
|
|
55
|
+
try {
|
|
56
|
+
fromFile = JSON.parse(await readFile(path, 'utf8'));
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// No config yet is normal — a fresh machine or a CI runner.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const parsed = configSchema.safeParse(fromFile);
|
|
64
|
+
const base = parsed.success ? parsed.data : configSchema.parse({});
|
|
65
|
+
return {
|
|
66
|
+
// BUILDATLAS_* is the current spelling; ATLAS_* still works so existing CI
|
|
67
|
+
// jobs keep running after the rename.
|
|
68
|
+
apiUrl: process.env.BUILDATLAS_API_URL ?? process.env.ATLAS_API_URL ?? base.apiUrl,
|
|
69
|
+
token: process.env.BUILDATLAS_TOKEN ?? process.env.ATLAS_TOKEN ?? base.token,
|
|
70
|
+
email: base.email,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export async function saveConfig(config) {
|
|
74
|
+
const path = configPath();
|
|
75
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
76
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
|
|
77
|
+
// writeFile only applies the mode when creating the file; enforce it for the
|
|
78
|
+
// overwrite case too so an existing world-readable file gets locked down.
|
|
79
|
+
await chmod(path, 0o600);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The project slug from the environment.
|
|
83
|
+
*
|
|
84
|
+
* BUILDATLAS_PROJECT is the current spelling; ATLAS_PROJECT is still honoured so
|
|
85
|
+
* CI jobs written before the CLI was renamed keep working.
|
|
86
|
+
*/
|
|
87
|
+
export function defaultProject() {
|
|
88
|
+
return process.env.BUILDATLAS_PROJECT ?? process.env.ATLAS_PROJECT;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Works out which project a command applies to.
|
|
92
|
+
*
|
|
93
|
+
* Order: `--project`, then the environment, then the app you are standing in.
|
|
94
|
+
* Reading it off disk is the point — you are already in the project directory, so
|
|
95
|
+
* requiring an env var to say so is make-work, and forgetting it produced "No
|
|
96
|
+
* project specified" for a project that was right there.
|
|
97
|
+
*
|
|
98
|
+
* `expo.extra.buildatlas.project` wins over `expo.slug`, for the case where the
|
|
99
|
+
* BuildAtlas project is named differently from the Expo one.
|
|
100
|
+
*
|
|
101
|
+
* Inference is reported by callers rather than applied silently: guessing wrong
|
|
102
|
+
* and uploading a keystore to another project is worse than an error.
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* The app config as Expo itself resolves it.
|
|
106
|
+
*
|
|
107
|
+
* `npx expo config --type public` is Expo's own resolver, so a dynamic
|
|
108
|
+
* `app.config.js` — plugins, environment switches, computed identifiers and all —
|
|
109
|
+
* comes back fully evaluated. That is the only way to read a dynamic config
|
|
110
|
+
* correctly; anything else is guessing at what the JavaScript would have returned.
|
|
111
|
+
*
|
|
112
|
+
* An earlier version of this CLI refused to do this on the grounds that it means
|
|
113
|
+
* running the project's own code. That was the wrong line to draw: `buildatlas
|
|
114
|
+
* build` already runs that code on the runner during prebuild and bundling, this
|
|
115
|
+
* runs in the developer's own project at their own request, and it is the exact
|
|
116
|
+
* command Expo's documentation tells people to run. Refusing only meant every
|
|
117
|
+
* command needed `--project` spelled out.
|
|
118
|
+
*
|
|
119
|
+
* Slow — a few seconds, because it loads the project's config chain — so it is only
|
|
120
|
+
* reached when there is no static `app.json` to read instead.
|
|
121
|
+
*/
|
|
122
|
+
async function readExpoConfig(dir) {
|
|
123
|
+
const dynamic = await dynamicConfigIn(dir);
|
|
124
|
+
if (!dynamic)
|
|
125
|
+
return undefined;
|
|
126
|
+
// Printed because it is noticeably slower than reading a file, and silence here
|
|
127
|
+
// looks like a hang.
|
|
128
|
+
process.stderr.write(pc.dim(` reading ${dynamic} via \`expo config\`…\n`));
|
|
129
|
+
try {
|
|
130
|
+
const { stdout } = await execFile('npx', ['--yes', 'expo', 'config', '--type', 'public', '--json'], {
|
|
131
|
+
cwd: dir,
|
|
132
|
+
// Expo prints notices before the JSON, and a large config is a large payload.
|
|
133
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
134
|
+
timeout: 120_000,
|
|
135
|
+
});
|
|
136
|
+
// Anything before the first brace is Expo's own chatter.
|
|
137
|
+
const start = stdout.indexOf('{');
|
|
138
|
+
if (start === -1)
|
|
139
|
+
return undefined;
|
|
140
|
+
const parsed = JSON.parse(stdout.slice(start));
|
|
141
|
+
return {
|
|
142
|
+
slug: parsed.extra?.buildatlas?.project ?? parsed.slug,
|
|
143
|
+
name: parsed.name,
|
|
144
|
+
version: parsed.version,
|
|
145
|
+
owner: parsed.owner,
|
|
146
|
+
easProjectId: parsed.extra?.eas?.projectId,
|
|
147
|
+
bundleIdentifier: parsed.ios?.bundleIdentifier,
|
|
148
|
+
androidPackage: parsed.android?.package,
|
|
149
|
+
fromDynamicConfig: dynamic,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
// Not fatal: the caller falls back to asking for --slug, and the reason is worth
|
|
154
|
+
// showing because "expo config" failing usually means dependencies are not
|
|
155
|
+
// installed, which the build would trip over too.
|
|
156
|
+
process.stderr.write(pc.dim(` (could not evaluate ${dynamic}: ${err.message.split('\n')[0]})\n`));
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Everything a caller might want from the app config, static or dynamic. */
|
|
161
|
+
export async function readResolvedAppConfig(dir) {
|
|
162
|
+
try {
|
|
163
|
+
const raw = await readFile(join(dir, 'app.json'), 'utf8');
|
|
164
|
+
const expo = JSON.parse(raw).expo ?? {};
|
|
165
|
+
return {
|
|
166
|
+
slug: expo.extra?.buildatlas?.project ?? expo.slug,
|
|
167
|
+
name: expo.name,
|
|
168
|
+
version: expo.version,
|
|
169
|
+
owner: expo.owner,
|
|
170
|
+
easProjectId: expo.extra?.eas?.projectId,
|
|
171
|
+
bundleIdentifier: expo.ios?.bundleIdentifier,
|
|
172
|
+
androidPackage: expo.android?.package,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// No static config; ask Expo.
|
|
177
|
+
}
|
|
178
|
+
return readExpoConfig(dir);
|
|
179
|
+
}
|
|
180
|
+
export async function resolveProject(explicit, dir = process.cwd()) {
|
|
181
|
+
if (explicit)
|
|
182
|
+
return { slug: explicit, source: 'flag' };
|
|
183
|
+
const fromEnv = defaultProject();
|
|
184
|
+
if (fromEnv)
|
|
185
|
+
return { slug: fromEnv, source: 'env' };
|
|
186
|
+
// Only app.json. Evaluating a dynamic app.config.js means running the project's
|
|
187
|
+
// own JavaScript just to learn a name, which is not a trade worth making.
|
|
188
|
+
try {
|
|
189
|
+
const raw = await readFile(join(dir, 'app.json'), 'utf8');
|
|
190
|
+
const expo = JSON.parse(raw).expo ?? {};
|
|
191
|
+
const configured = expo.extra?.buildatlas?.project;
|
|
192
|
+
if (typeof configured === 'string' && configured) {
|
|
193
|
+
return { slug: configured, source: 'config' };
|
|
194
|
+
}
|
|
195
|
+
if (typeof expo.slug === 'string' && expo.slug) {
|
|
196
|
+
return { slug: expo.slug, source: 'app.json' };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// No app.json, or unparseable. Fall through to the dynamic config below.
|
|
201
|
+
}
|
|
202
|
+
// Only now, because it costs seconds where reading a file costs nothing.
|
|
203
|
+
const dynamic = await readExpoConfig(dir);
|
|
204
|
+
if (dynamic?.slug) {
|
|
205
|
+
return { slug: dynamic.slug, source: 'app.config.js' };
|
|
206
|
+
}
|
|
207
|
+
throw new Error('No project specified. Pass --project <slug>, set BUILDATLAS_PROJECT, or run this ' +
|
|
208
|
+
`from a directory whose app.json has an "expo.slug".\n${await noProjectAdvice(dir)}`);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* The dynamic config filenames Expo accepts, in its own resolution order.
|
|
212
|
+
*
|
|
213
|
+
* Used only to explain a failure. A project with one of these has no app.json and
|
|
214
|
+
* never will, so telling its owner to go and find one wastes their afternoon — which
|
|
215
|
+
* is exactly what the old message did.
|
|
216
|
+
*/
|
|
217
|
+
const DYNAMIC_CONFIGS = ['app.config.ts', 'app.config.js', 'app.config.mjs', 'app.config.cjs'];
|
|
218
|
+
async function dynamicConfigIn(dir) {
|
|
219
|
+
for (const name of DYNAMIC_CONFIGS) {
|
|
220
|
+
try {
|
|
221
|
+
await readFile(join(dir, name), 'utf8');
|
|
222
|
+
return name;
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Not this one.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* What to tell someone whose directory has no usable static config.
|
|
232
|
+
*
|
|
233
|
+
* Shared so `build`, `projects create` and everything else give the same answer,
|
|
234
|
+
* and so the two genuinely different causes get genuinely different advice: a
|
|
235
|
+
* dynamic config, which we will not evaluate, versus an app that lives in a
|
|
236
|
+
* subdirectory.
|
|
237
|
+
*/
|
|
238
|
+
export async function noProjectAdvice(dir) {
|
|
239
|
+
const dynamic = await dynamicConfigIn(dir);
|
|
240
|
+
if (dynamic) {
|
|
241
|
+
// Reaching here means `expo config` was tried and did not yield a slug — so the
|
|
242
|
+
// advice is about why that failed, not about passing flags instead.
|
|
243
|
+
return (`Found ${dynamic}, but evaluating it with \`expo config\` produced no slug.\n` +
|
|
244
|
+
` Check it runs at all: npx expo config --type public\n` +
|
|
245
|
+
` A failure there is usually missing dependencies (run your install first) or an ` +
|
|
246
|
+
`error thrown by the config itself.\n` +
|
|
247
|
+
` To skip evaluation entirely, pass --project <slug>, or put an app.json next to it ` +
|
|
248
|
+
`with just "expo": { "extra": { "buildatlas": { "project": "<slug>" } } } — that is read ` +
|
|
249
|
+
`directly and does not conflict with ${dynamic}.`);
|
|
250
|
+
}
|
|
251
|
+
return (`No app.json or app.config.js in ${dir}. If the app lives in a subdirectory — common in a ` +
|
|
252
|
+
`monorepo — point at it with --dir <path> for 'projects create', or run the command from ` +
|
|
253
|
+
`there.`);
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/detach.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Makes Ctrl-C detach from a build rather than look like it stopped one.
|
|
3
|
+
*
|
|
4
|
+
* Nothing in the CLI ever cancelled a build on Ctrl-C — the signal only killed the
|
|
5
|
+
* local process, and the build carried on. But it exited in silence, which is
|
|
6
|
+
* indistinguishable from having stopped it, so people reasonably assume they just
|
|
7
|
+
* killed their build.
|
|
8
|
+
*
|
|
9
|
+
* Cancelling is a deliberate act with a cost: it throws away however many minutes
|
|
10
|
+
* of compute have already gone in, and on a shared runner it is someone else's
|
|
11
|
+
* queue position too. So it stays an explicit command, never a keystroke, and this
|
|
12
|
+
* says so at the moment the question arises.
|
|
13
|
+
*
|
|
14
|
+
* A second Ctrl-C exits immediately, because a person pressing it twice wants out
|
|
15
|
+
* of the terminal, not another paragraph.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detachOnInterrupt(buildId: string): () => void;
|
|
18
|
+
//# sourceMappingURL=detach.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detach.d.ts","sourceRoot":"","sources":["../src/detach.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,IAAI,CA8B7D"}
|
package/dist/detach.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
/**
|
|
3
|
+
* Makes Ctrl-C detach from a build rather than look like it stopped one.
|
|
4
|
+
*
|
|
5
|
+
* Nothing in the CLI ever cancelled a build on Ctrl-C — the signal only killed the
|
|
6
|
+
* local process, and the build carried on. But it exited in silence, which is
|
|
7
|
+
* indistinguishable from having stopped it, so people reasonably assume they just
|
|
8
|
+
* killed their build.
|
|
9
|
+
*
|
|
10
|
+
* Cancelling is a deliberate act with a cost: it throws away however many minutes
|
|
11
|
+
* of compute have already gone in, and on a shared runner it is someone else's
|
|
12
|
+
* queue position too. So it stays an explicit command, never a keystroke, and this
|
|
13
|
+
* says so at the moment the question arises.
|
|
14
|
+
*
|
|
15
|
+
* A second Ctrl-C exits immediately, because a person pressing it twice wants out
|
|
16
|
+
* of the terminal, not another paragraph.
|
|
17
|
+
*/
|
|
18
|
+
export function detachOnInterrupt(buildId) {
|
|
19
|
+
let warned = false;
|
|
20
|
+
const onInterrupt = () => {
|
|
21
|
+
if (warned) {
|
|
22
|
+
// 130 is the conventional "terminated by SIGINT" status.
|
|
23
|
+
process.exit(130);
|
|
24
|
+
}
|
|
25
|
+
warned = true;
|
|
26
|
+
console.log(`\n${pc.yellow('detached')} — the build is still running on the server.\n` +
|
|
27
|
+
` follow again : ${pc.bold(`buildatlas logs ${buildId}`)}\n` +
|
|
28
|
+
` stop it : ${pc.bold(`buildatlas cancel ${buildId}`)}\n` +
|
|
29
|
+
pc.dim(' (press Ctrl-C again to leave immediately)'));
|
|
30
|
+
// Exit cleanly rather than non-zero: detaching is not a build failure, and a
|
|
31
|
+
// non-zero status here would fail a CI step that was only being tidied up.
|
|
32
|
+
process.exit(0);
|
|
33
|
+
};
|
|
34
|
+
process.on('SIGINT', onInterrupt);
|
|
35
|
+
// SIGTERM too: a closed terminal or a `kill` should read the same way.
|
|
36
|
+
process.on('SIGTERM', onInterrupt);
|
|
37
|
+
return () => {
|
|
38
|
+
process.off('SIGINT', onInterrupt);
|
|
39
|
+
process.off('SIGTERM', onInterrupt);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=detach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detach.js","sourceRoot":"","sources":["../src/detach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,IAAI,MAAM,EAAE,CAAC;YACX,yDAAyD;YACzD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,MAAM,GAAG,IAAI,CAAC;QAEd,OAAO,CAAC,GAAG,CACT,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,gDAAgD;YACxE,oBAAoB,EAAE,CAAC,IAAI,CAAC,mBAAmB,OAAO,EAAE,CAAC,IAAI;YAC7D,oBAAoB,EAAE,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,IAAI;YAC/D,EAAE,CAAC,GAAG,CAAC,6CAA6C,CAAC,CACxD,CAAC;QAEF,6EAA6E;QAC7E,2EAA2E;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAClC,uEAAuE;IACvE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAEnC,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACtC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the zip `eas credentials` hands you when you download a distribution
|
|
3
|
+
* certificate.
|
|
4
|
+
*
|
|
5
|
+
* The archive looks like this:
|
|
6
|
+
*
|
|
7
|
+
* DistCert_C8FL4SPYK4.p12 the certificate *and* private key
|
|
8
|
+
* DistCertPrivateKey_C8FL4SPYK4.txt the same key again, as PEM
|
|
9
|
+
* DistCertCredentials_C8FL4SPYK4.md prose, containing the .p12 password
|
|
10
|
+
*
|
|
11
|
+
* The password is machine-generated and 24 characters long, so transcribing it by
|
|
12
|
+
* hand is both tedious and the most likely place to introduce a typo — one that then
|
|
13
|
+
* surfaces as a keychain error mid-build rather than as "wrong password". Since the
|
|
14
|
+
* archive already contains it, read it.
|
|
15
|
+
*
|
|
16
|
+
* `unzip -p` rather than a zip library: it is present on macOS and every Linux that
|
|
17
|
+
* can run a build, and this avoids a dependency for one file format. Entries are
|
|
18
|
+
* streamed to stdout, never written to disk, so nothing has to be cleaned up
|
|
19
|
+
* afterwards and a crash cannot leave a private key in a temp directory.
|
|
20
|
+
*/
|
|
21
|
+
export interface EasCertificateBundle {
|
|
22
|
+
p12: Buffer;
|
|
23
|
+
password?: string;
|
|
24
|
+
/** For the label, and so the log can say which file it came from. */
|
|
25
|
+
p12Name: string;
|
|
26
|
+
/** Present when the archive also ships the key separately, which EAS's does. */
|
|
27
|
+
hasSeparateKey: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Pulls the certificate and its password out of an EAS credentials zip.
|
|
31
|
+
*
|
|
32
|
+
* Returns undefined when the archive is not one of these, so the caller can fall
|
|
33
|
+
* back to treating the path as a plain `.p12` rather than guessing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readEasCertificateZip(zipPath: string): Promise<EasCertificateBundle | undefined>;
|
|
36
|
+
/** Whether a path is worth trying to read as a credentials archive. */
|
|
37
|
+
export declare function looksLikeZip(path: string): boolean;
|
|
38
|
+
//# sourceMappingURL=eas-credentials-zip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eas-credentials-zip.d.ts","sourceRoot":"","sources":["../src/eas-credentials-zip.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;CACzB;AAkBD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAoC3C;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFile = promisify(execFileCb);
|
|
4
|
+
async function listEntries(zipPath) {
|
|
5
|
+
const { stdout } = await execFile('unzip', ['-Z', '-1', zipPath], { maxBuffer: 1024 * 1024 });
|
|
6
|
+
return stdout
|
|
7
|
+
.split('\n')
|
|
8
|
+
.map((l) => l.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
}
|
|
11
|
+
async function readEntry(zipPath, entry) {
|
|
12
|
+
const { stdout } = await execFile('unzip', ['-p', zipPath, entry], {
|
|
13
|
+
encoding: 'buffer',
|
|
14
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
15
|
+
});
|
|
16
|
+
return stdout;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Pulls the certificate and its password out of an EAS credentials zip.
|
|
20
|
+
*
|
|
21
|
+
* Returns undefined when the archive is not one of these, so the caller can fall
|
|
22
|
+
* back to treating the path as a plain `.p12` rather than guessing.
|
|
23
|
+
*/
|
|
24
|
+
export async function readEasCertificateZip(zipPath) {
|
|
25
|
+
let entries;
|
|
26
|
+
try {
|
|
27
|
+
entries = await listEntries(zipPath);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Not a readable zip, or no `unzip` on this machine. Either way the caller's
|
|
31
|
+
// plain-file path is the right fallback.
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const p12Name = entries.find((e) => e.toLowerCase().endsWith('.p12'));
|
|
35
|
+
if (!p12Name)
|
|
36
|
+
return undefined;
|
|
37
|
+
const p12 = await readEntry(zipPath, p12Name);
|
|
38
|
+
// The password sits in a markdown file as a labelled line:
|
|
39
|
+
// - Apple Distribution Certificate password: <24 chars>
|
|
40
|
+
// Matched on the label rather than the filename, since only the label is
|
|
41
|
+
// documented behaviour and the filename carries a per-certificate suffix.
|
|
42
|
+
let password;
|
|
43
|
+
const notes = entries.filter((e) => e.toLowerCase().endsWith('.md'));
|
|
44
|
+
for (const note of notes) {
|
|
45
|
+
const text = (await readEntry(zipPath, note)).toString('utf8');
|
|
46
|
+
const match = text.match(/password:\s*(\S+)/i);
|
|
47
|
+
if (match?.[1]) {
|
|
48
|
+
password = match[1];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
p12,
|
|
54
|
+
password,
|
|
55
|
+
p12Name,
|
|
56
|
+
hasSeparateKey: entries.some((e) => /privatekey.*\.txt$/i.test(e)),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Whether a path is worth trying to read as a credentials archive. */
|
|
60
|
+
export function looksLikeZip(path) {
|
|
61
|
+
return path.toLowerCase().endsWith('.zip');
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=eas-credentials-zip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eas-credentials-zip.js","sourceRoot":"","sources":["../src/eas-credentials-zip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;AAgCvC,KAAK,UAAU,WAAW,CAAC,OAAe;IACxC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IAC9F,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,KAAa;IACrD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE;QACjE,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC5B,CAAC,CAAC;IACH,OAAO,MAA2B,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAe;IAEf,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;QAC7E,yCAAyC;QACzC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE9C,2DAA2D;IAC3D,0DAA0D;IAC1D,yEAAyE;IACzE,0EAA0E;IAC1E,IAAI,QAA4B,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACpB,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG;QACH,QAAQ;QACR,OAAO;QACP,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deliberately untyped/loose — this is a read-only, best-effort peek at eas.json
|
|
3
|
+
* from the CLI side. Full validation belongs to the worker (`@buildatlas/shared`'s
|
|
4
|
+
* `eas-config.ts`), which the CLI does not depend on: it ships as a standalone
|
|
5
|
+
* published npm package, and `@buildatlas/shared` is a private workspace package
|
|
6
|
+
* that would not resolve for anyone who `npm install`s `buildatlas`.
|
|
7
|
+
*/
|
|
8
|
+
export interface ParsedEasJson {
|
|
9
|
+
build?: Record<string, {
|
|
10
|
+
extends?: string;
|
|
11
|
+
env?: Record<string, string>;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare function readEasJson(projectDir: string): Promise<ParsedEasJson>;
|
|
15
|
+
/**
|
|
16
|
+
* Flattens a profile's `env` block by walking its `extends` chain root-first —
|
|
17
|
+
* the same precedence eas-cli (and BuildAtlas's worker, see
|
|
18
|
+
* `packages/shared/src/eas-config.ts`'s `resolveProfile`) use.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveProfileEnv(easJson: ParsedEasJson, profileName: string): Record<string, string>;
|
|
21
|
+
//# sourceMappingURL=eas-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eas-json.d.ts","sourceRoot":"","sources":["../src/eas-json.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;CAC5E;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAG5E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBxB"}
|
package/dist/eas-json.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export async function readEasJson(projectDir) {
|
|
4
|
+
const raw = await readFile(join(projectDir, 'eas.json'), 'utf8');
|
|
5
|
+
return JSON.parse(raw);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Flattens a profile's `env` block by walking its `extends` chain root-first —
|
|
9
|
+
* the same precedence eas-cli (and BuildAtlas's worker, see
|
|
10
|
+
* `packages/shared/src/eas-config.ts`'s `resolveProfile`) use.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveProfileEnv(easJson, profileName) {
|
|
13
|
+
const profiles = easJson.build ?? {};
|
|
14
|
+
const chain = [];
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
let cursor = profileName;
|
|
17
|
+
while (cursor) {
|
|
18
|
+
// A circular `extends` here is a pre-existing eas.json problem; the actual
|
|
19
|
+
// build will fail loudly on it later, so this just stops walking rather than
|
|
20
|
+
// duplicating that validation.
|
|
21
|
+
if (seen.has(cursor))
|
|
22
|
+
break;
|
|
23
|
+
seen.add(cursor);
|
|
24
|
+
const profile = profiles[cursor];
|
|
25
|
+
if (!profile)
|
|
26
|
+
break;
|
|
27
|
+
chain.unshift(profile.env ?? {});
|
|
28
|
+
cursor = profile.extends;
|
|
29
|
+
}
|
|
30
|
+
return chain.reduce((acc, env) => ({ ...acc, ...env }), {});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=eas-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eas-json.js","sourceRoot":"","sources":["../src/eas-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAajC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAsB,EACtB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IACrC,MAAM,KAAK,GAA6B,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,IAAI,MAAM,GAAuB,WAAW,CAAC;IAC7C,OAAO,MAAM,EAAE,CAAC;QACd,2EAA2E;QAC3E,6EAA6E;QAC7E,+BAA+B;QAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,MAAM;QAC5B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjB,MAAM,OAAO,GACX,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,IAAI,CAAC,OAAO;YAAE,MAAM;QACpB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACjC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAC9D,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { registerAuthCommands } from './commands/auth.js';
|
|
6
|
+
import { registerBuildCommand } from './commands/build.js';
|
|
7
|
+
import { registerBuildQueryCommands } from './commands/builds.js';
|
|
8
|
+
import { registerCredentialCommands } from './commands/credentials.js';
|
|
9
|
+
import { registerEnvCommand } from './commands/env.js';
|
|
10
|
+
import { registerExpoTokenCommands } from './commands/expo-tokens.js';
|
|
11
|
+
import { registerInitCommand } from './commands/init.js';
|
|
12
|
+
import { registerProjectCommands } from './commands/projects.js';
|
|
13
|
+
import { registerSubmitCommand } from './commands/submit.js';
|
|
14
|
+
import { registerUpdateCommand } from './commands/update.js';
|
|
15
|
+
import { AtlasApiError, apiRequest } from './client.js';
|
|
16
|
+
import { loadConfig } from './config.js';
|
|
17
|
+
// Read the version rather than repeating it. It was hardcoded here, drifted from
|
|
18
|
+
// package.json, and a CLI whose --version lies is worse than one that has none:
|
|
19
|
+
// it makes "did my install actually update?" unanswerable.
|
|
20
|
+
//
|
|
21
|
+
// '../package.json' resolves to the same file from src/index.ts in dev and from
|
|
22
|
+
// dist/index.js once built.
|
|
23
|
+
const { version } = createRequire(import.meta.url)('../package.json');
|
|
24
|
+
const program = new Command();
|
|
25
|
+
program
|
|
26
|
+
.name('buildatlas')
|
|
27
|
+
.description('BuildAtlas CLI — self-hosted builds for Expo, React Native, iOS and Android.')
|
|
28
|
+
.version(version);
|
|
29
|
+
registerAuthCommands(program);
|
|
30
|
+
registerInitCommand(program);
|
|
31
|
+
registerBuildCommand(program);
|
|
32
|
+
registerBuildQueryCommands(program);
|
|
33
|
+
registerCredentialCommands(program);
|
|
34
|
+
registerSubmitCommand(program);
|
|
35
|
+
registerEnvCommand(program);
|
|
36
|
+
registerExpoTokenCommands(program);
|
|
37
|
+
registerProjectCommands(program);
|
|
38
|
+
registerUpdateCommand(program);
|
|
39
|
+
program
|
|
40
|
+
.command('whoami')
|
|
41
|
+
.description('Show the authenticated user')
|
|
42
|
+
.action(async () => {
|
|
43
|
+
const config = await loadConfig();
|
|
44
|
+
if (!config.token) {
|
|
45
|
+
console.error(pc.red('Not logged in.'), 'Run', pc.bold('buildatlas login'));
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Ask the server rather than reporting what is in the config file. A revoked
|
|
50
|
+
// token still leaves an email on disk, and "whoami says I am logged in but
|
|
51
|
+
// every other command fails" is a genuinely confusing place to start
|
|
52
|
+
// debugging.
|
|
53
|
+
try {
|
|
54
|
+
const { user } = await apiRequest(config, '/auth/me', {
|
|
55
|
+
token: config.token,
|
|
56
|
+
});
|
|
57
|
+
console.log(`${user.email} @ ${config.apiUrl}`);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
const reason = err instanceof AtlasApiError ? err.message : err.message;
|
|
61
|
+
console.error(pc.red('✖'), `Stored token is not usable: ${reason}`);
|
|
62
|
+
console.error(pc.dim(` re-run: buildatlas login --api ${config.apiUrl}`));
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
await program.parseAsync(process.argv);
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logs.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AtlasConfig } from './config.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Follows a build's log over SSE and resolves with its terminal status.
|
|
4
|
+
*
|
|
5
|
+
* Reconnects on a dropped connection, resuming from the last sequence number
|
|
6
|
+
* seen. That cursor is the whole reason the server numbers chunks: a build can run
|
|
7
|
+
* 20 minutes, and a laptop closing its lid mid-build should not truncate the log
|
|
8
|
+
* or replay it from the top.
|
|
9
|
+
*/
|
|
10
|
+
export declare function streamLogs(config: Pick<AtlasConfig, 'apiUrl' | 'token'>, buildId: string, { quiet }?: {
|
|
11
|
+
quiet?: boolean | undefined;
|
|
12
|
+
}): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS/C;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,EAC7C,OAAO,EAAE,MAAM,EACf,EAAE,KAAa,EAAE;;CAAK,GACrB,OAAO,CAAC,MAAM,CAAC,CA+DjB"}
|