@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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -2
  3. package/dist/browser-login.d.ts +12 -0
  4. package/dist/browser-login.d.ts.map +1 -0
  5. package/dist/browser-login.js +94 -0
  6. package/dist/browser-login.js.map +1 -0
  7. package/dist/client.d.ts +33 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +115 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/client.test.d.ts +2 -0
  12. package/dist/client.test.d.ts.map +1 -0
  13. package/dist/client.test.js +102 -0
  14. package/dist/client.test.js.map +1 -0
  15. package/dist/commands/auth.d.ts +3 -0
  16. package/dist/commands/auth.d.ts.map +1 -0
  17. package/dist/commands/auth.js +88 -0
  18. package/dist/commands/auth.js.map +1 -0
  19. package/dist/commands/build.d.ts +4 -0
  20. package/dist/commands/build.d.ts.map +1 -0
  21. package/dist/commands/build.js +297 -0
  22. package/dist/commands/build.js.map +1 -0
  23. package/dist/commands/builds.d.ts +3 -0
  24. package/dist/commands/builds.d.ts.map +1 -0
  25. package/dist/commands/builds.js +102 -0
  26. package/dist/commands/builds.js.map +1 -0
  27. package/dist/commands/credentials-wizard.d.ts +25 -0
  28. package/dist/commands/credentials-wizard.d.ts.map +1 -0
  29. package/dist/commands/credentials-wizard.js +274 -0
  30. package/dist/commands/credentials-wizard.js.map +1 -0
  31. package/dist/commands/credentials.d.ts +3 -0
  32. package/dist/commands/credentials.d.ts.map +1 -0
  33. package/dist/commands/credentials.js +249 -0
  34. package/dist/commands/credentials.js.map +1 -0
  35. package/dist/commands/env.d.ts +37 -0
  36. package/dist/commands/env.d.ts.map +1 -0
  37. package/dist/commands/env.js +220 -0
  38. package/dist/commands/env.js.map +1 -0
  39. package/dist/commands/expo-tokens.d.ts +3 -0
  40. package/dist/commands/expo-tokens.d.ts.map +1 -0
  41. package/dist/commands/expo-tokens.js +103 -0
  42. package/dist/commands/expo-tokens.js.map +1 -0
  43. package/dist/commands/init.d.ts +6 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +204 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/projects.d.ts +11 -0
  48. package/dist/commands/projects.d.ts.map +1 -0
  49. package/dist/commands/projects.js +148 -0
  50. package/dist/commands/projects.js.map +1 -0
  51. package/dist/commands/submit.d.ts +10 -0
  52. package/dist/commands/submit.d.ts.map +1 -0
  53. package/dist/commands/submit.js +118 -0
  54. package/dist/commands/submit.js.map +1 -0
  55. package/dist/commands/update.d.ts +10 -0
  56. package/dist/commands/update.d.ts.map +1 -0
  57. package/dist/commands/update.js +93 -0
  58. package/dist/commands/update.js.map +1 -0
  59. package/dist/config.d.ts +66 -0
  60. package/dist/config.d.ts.map +1 -0
  61. package/dist/config.js +255 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/detach.d.ts +18 -0
  64. package/dist/detach.d.ts.map +1 -0
  65. package/dist/detach.js +42 -0
  66. package/dist/detach.js.map +1 -0
  67. package/dist/eas-credentials-zip.d.ts +38 -0
  68. package/dist/eas-credentials-zip.d.ts.map +1 -0
  69. package/dist/eas-credentials-zip.js +63 -0
  70. package/dist/eas-credentials-zip.js.map +1 -0
  71. package/dist/eas-json.d.ts +21 -0
  72. package/dist/eas-json.d.ts.map +1 -0
  73. package/dist/eas-json.js +32 -0
  74. package/dist/eas-json.js.map +1 -0
  75. package/dist/index.d.ts +3 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +67 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/logs.d.ts +13 -0
  80. package/dist/logs.d.ts.map +1 -0
  81. package/dist/logs.js +70 -0
  82. package/dist/logs.js.map +1 -0
  83. package/dist/packaging.test.d.ts +2 -0
  84. package/dist/packaging.test.d.ts.map +1 -0
  85. package/dist/packaging.test.js +79 -0
  86. package/dist/packaging.test.js.map +1 -0
  87. package/dist/profiles.test.d.ts +2 -0
  88. package/dist/profiles.test.d.ts.map +1 -0
  89. package/dist/profiles.test.js +56 -0
  90. package/dist/profiles.test.js.map +1 -0
  91. package/dist/project-hint.d.ts +12 -0
  92. package/dist/project-hint.d.ts.map +1 -0
  93. package/dist/project-hint.js +19 -0
  94. package/dist/project-hint.js.map +1 -0
  95. package/dist/project-type.d.ts +43 -0
  96. package/dist/project-type.d.ts.map +1 -0
  97. package/dist/project-type.js +88 -0
  98. package/dist/project-type.js.map +1 -0
  99. package/dist/project-type.test.d.ts +2 -0
  100. package/dist/project-type.test.d.ts.map +1 -0
  101. package/dist/project-type.test.js +77 -0
  102. package/dist/project-type.test.js.map +1 -0
  103. package/dist/prompt.d.ts +56 -0
  104. package/dist/prompt.d.ts.map +1 -0
  105. package/dist/prompt.js +157 -0
  106. package/dist/prompt.js.map +1 -0
  107. package/dist/tarball.d.ts +39 -0
  108. package/dist/tarball.d.ts.map +1 -0
  109. package/dist/tarball.js +208 -0
  110. package/dist/tarball.js.map +1 -0
  111. package/dist/tarball.test.d.ts +2 -0
  112. package/dist/tarball.test.d.ts.map +1 -0
  113. package/dist/tarball.test.js +97 -0
  114. package/dist/tarball.test.js.map +1 -0
  115. package/package.json +56 -4
@@ -0,0 +1,220 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import pc from 'picocolors';
4
+ import { AtlasApiError, apiRequest } from '../client.js';
5
+ import { loadConfig, resolveProject } from '../config.js';
6
+ import { readEasJson, resolveProfileEnv } from '../eas-json.js';
7
+ import { reportProject } from '../project-hint.js';
8
+ /**
9
+ * Copies a profile's `eas.json` env block into the project's BuildAtlas env
10
+ * store. Add-only by default: a value someone already set (or edited) in the
11
+ * dashboard is never silently replaced by whatever a committed eas.json says.
12
+ *
13
+ * Non-fatal by design at the call sites that treat this as a side effect (e.g.
14
+ * `buildatlas build --local`) — the build's own env still comes correctly from
15
+ * the worker merging eas.json directly (see the worker's `inject_env` phase),
16
+ * so a failure here (e.g. a non-admin token, since setting env requires admin)
17
+ * should never block a build.
18
+ */
19
+ export async function seedEnvFromEasJson(params) {
20
+ const easJson = await readEasJson(params.projectDir);
21
+ const profileEnv = resolveProfileEnv(easJson, params.profile);
22
+ const keys = Object.keys(profileEnv);
23
+ if (!keys.length)
24
+ return { added: [], skipped: [] };
25
+ const { env: existing } = await apiRequest(params.config, `/projects/${params.slug}/env`, { token: params.config.token });
26
+ const existingKeys = new Set(existing.map((e) => e.key));
27
+ const added = [];
28
+ const skipped = [];
29
+ for (const key of keys) {
30
+ if (existingKeys.has(key) && !params.overwrite) {
31
+ skipped.push(key);
32
+ continue;
33
+ }
34
+ await apiRequest(params.config, `/projects/${params.slug}/env`, {
35
+ method: 'PUT',
36
+ token: params.config.token,
37
+ body: JSON.stringify({
38
+ key,
39
+ value: profileEnv[key],
40
+ profiles: [params.profile],
41
+ visibility: 'plaintext',
42
+ }),
43
+ });
44
+ added.push(key);
45
+ }
46
+ return { added, skipped };
47
+ }
48
+ /**
49
+ * Parses a `.env` file.
50
+ *
51
+ * Deliberately small: `KEY=value`, `#` comments, blank lines, and quotes stripped
52
+ * from a fully quoted value. No interpolation, no `export` prefixes, no multiline —
53
+ * a file that needs those is doing something this importer should not silently
54
+ * half-understand.
55
+ *
56
+ * Values are taken verbatim otherwise, including `=` inside them, because URLs and
57
+ * base64 both contain it.
58
+ */
59
+ export function parseDotEnv(text) {
60
+ const out = {};
61
+ for (const rawLine of text.split(/\r?\n/)) {
62
+ const line = rawLine.trim();
63
+ if (!line || line.startsWith('#'))
64
+ continue;
65
+ const eq = line.indexOf('=');
66
+ if (eq <= 0)
67
+ continue;
68
+ const key = line.slice(0, eq).trim().replace(/^export\s+/, '');
69
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
70
+ continue;
71
+ let value = line.slice(eq + 1).trim();
72
+ if ((value.startsWith('"') && value.endsWith('"') && value.length > 1) ||
73
+ (value.startsWith("'") && value.endsWith("'") && value.length > 1)) {
74
+ value = value.slice(1, -1);
75
+ }
76
+ out[key] = value;
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * Copies a `.env` file into the BuildAtlas env store for one profile.
82
+ *
83
+ * Exists because eas.json's `environment` field points at variables stored on EAS's
84
+ * servers, which nothing outside EAS can read — so a project moving over has to get
85
+ * them across once. `eas env:pull --environment preview` writes exactly this kind of
86
+ * file, and so does copying them out of the EAS dashboard.
87
+ *
88
+ * `--secret` is the safer default for anything that is not obviously public: a
89
+ * plaintext entry stays readable in the dashboard, which is right for an API base URL
90
+ * and wrong for a token.
91
+ */
92
+ async function importDotEnv(params) {
93
+ const parsed = parseDotEnv(await readFile(params.file, 'utf8'));
94
+ const keys = Object.keys(parsed);
95
+ if (!keys.length) {
96
+ throw new Error(`No KEY=value lines found in ${params.file}.`);
97
+ }
98
+ const { env: existing } = await apiRequest(params.config, `/projects/${params.slug}/env`, { token: params.config.token });
99
+ const existingKeys = new Set(existing.map((e) => e.key));
100
+ const added = [];
101
+ const skipped = [];
102
+ for (const key of keys) {
103
+ if (existingKeys.has(key) && !params.overwrite) {
104
+ skipped.push(key);
105
+ continue;
106
+ }
107
+ await apiRequest(params.config, `/projects/${params.slug}/env`, {
108
+ method: 'PUT',
109
+ token: params.config.token,
110
+ body: JSON.stringify({
111
+ key,
112
+ value: parsed[key],
113
+ profiles: params.profile ? [params.profile] : [],
114
+ visibility: params.secret ? 'secret' : 'plaintext',
115
+ }),
116
+ });
117
+ added.push(key);
118
+ }
119
+ return { added, skipped };
120
+ }
121
+ export function registerEnvCommand(program) {
122
+ const env = program
123
+ .command('env')
124
+ .description("Sync a project's environment variables from eas.json or a .env file");
125
+ env
126
+ .command('pull')
127
+ .description('Import a .env file into the BuildAtlas env store')
128
+ .requiredOption('-f, --file <path>', 'Path to a .env file')
129
+ .option('-e, --profile <name>', 'Apply to one build profile only (default: all profiles)')
130
+ .option('--plaintext', 'Store readable in the dashboard, for values that are not secret')
131
+ .option('--overwrite', 'Replace keys that are already stored')
132
+ .option('--project <slug>', 'Project slug (default: $BUILDATLAS_PROJECT, else app config)')
133
+ .action(async (opts) => {
134
+ await run(async () => {
135
+ const config = await requireAuth();
136
+ const resolved = await resolveProject(opts.project);
137
+ reportProject(resolved);
138
+ const { added, skipped } = await importDotEnv({
139
+ config,
140
+ slug: resolved.slug,
141
+ file: resolve(opts.file),
142
+ profile: opts.profile,
143
+ overwrite: Boolean(opts.overwrite),
144
+ secret: !opts.plaintext,
145
+ });
146
+ if (added.length) {
147
+ console.log(`${pc.green('✔')} stored ${added.length} variable(s)${opts.profile ? ` for profile ${opts.profile}` : ''}: ${added.join(', ')}`);
148
+ }
149
+ if (skipped.length) {
150
+ // Not overwriting by default: an import should never quietly replace a
151
+ // value someone set deliberately in the dashboard.
152
+ console.log(pc.dim(` left alone (already set): ${skipped.join(', ')} — use --overwrite to replace`));
153
+ }
154
+ if (!opts.plaintext) {
155
+ console.log(pc.dim(' stored as secrets, so values are not readable again. --plaintext for URLs and other non-secrets.'));
156
+ }
157
+ });
158
+ });
159
+ env
160
+ .command('import')
161
+ .description("Copy a build profile's eas.json env block into the BuildAtlas env store")
162
+ .requiredOption('-e, --profile <profile>', 'eas.json build profile to import from')
163
+ .option('--project <slug>', 'BuildAtlas project slug (default: $BUILDATLAS_PROJECT, else app.json)')
164
+ .option('--dir <path>', 'Project directory', process.cwd())
165
+ .option('--overwrite', 'Replace values that already exist in the env store (default: add-only)')
166
+ .action(async (opts) => {
167
+ try {
168
+ const config = await loadConfig();
169
+ if (!config.token)
170
+ throw new Error('Not logged in. Run `buildatlas login` first.');
171
+ const projectDir = resolve(opts.dir);
172
+ const resolved = await resolveProject(opts.project, projectDir);
173
+ reportProject(resolved);
174
+ const { added, skipped } = await seedEnvFromEasJson({
175
+ config,
176
+ slug: resolved.slug,
177
+ projectDir,
178
+ profile: opts.profile,
179
+ overwrite: opts.overwrite ?? false,
180
+ });
181
+ if (added.length) {
182
+ console.log(`${pc.green('✔')} imported ${added.length}: ${added.join(', ')}`);
183
+ }
184
+ if (skipped.length) {
185
+ console.log(pc.dim(` skipped ${skipped.length} already set (use --overwrite to replace): `) +
186
+ pc.dim(skipped.join(', ')));
187
+ }
188
+ if (!added.length && !skipped.length) {
189
+ console.log(pc.dim(`No env vars in eas.json profile "${opts.profile}".`));
190
+ }
191
+ }
192
+ catch (err) {
193
+ const message = err instanceof AtlasApiError ? `${err.message} (${err.code})` : err.message;
194
+ console.error(pc.red('✖'), message);
195
+ process.exitCode = 1;
196
+ }
197
+ });
198
+ }
199
+ /**
200
+ * Local copies of the two helpers every command module keeps: fail with a readable
201
+ * message and a non-zero exit rather than a stack trace, and refuse early when there
202
+ * is no token instead of sending an unauthenticated request.
203
+ */
204
+ async function requireAuth() {
205
+ const config = await loadConfig();
206
+ if (!config.token)
207
+ throw new Error('Not logged in. Run `buildatlas login` first.');
208
+ return config;
209
+ }
210
+ async function run(fn) {
211
+ try {
212
+ await fn();
213
+ }
214
+ catch (err) {
215
+ const message = err instanceof AtlasApiError ? `${err.message} (${err.code})` : err.message;
216
+ console.error(pc.red('✖'), message);
217
+ process.exitCode = 1;
218
+ }
219
+ }
220
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerExpoTokenCommands(program: Command): void;
3
+ //# sourceMappingURL=expo-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-tokens.d.ts","sourceRoot":"","sources":["../../src/commands/expo-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8FhE"}
@@ -0,0 +1,103 @@
1
+ import pc from 'picocolors';
2
+ import { AtlasApiError, apiRequest } from '../client.js';
3
+ import { loadConfig } from '../config.js';
4
+ import { withPrompter } from '../prompt.js';
5
+ function describe(row) {
6
+ const scope = row.projectSlug ? `project ${row.projectSlug}` : pc.cyan('all projects');
7
+ const who = row.expoActorName
8
+ ? `${row.expoActorType === 'Robot' ? 'robot' : 'user'} ${pc.bold(row.expoActorName)}${row.expoAccounts.length ? ` · ${row.expoAccounts.join(', ')}` : ''}`
9
+ : pc.dim('not yet verified');
10
+ const problem = row.validationError ? `\n ${pc.red(row.validationError)}` : '';
11
+ return ` ${pc.bold(row.label)}\n ${scope} · ${who}\n ${pc.dim(`id ${row.id} · last used ${row.lastUsedAt ? new Date(row.lastUsedAt).toLocaleString() : 'never'}`)}${problem}`;
12
+ }
13
+ export function registerExpoTokenCommands(program) {
14
+ const group = program
15
+ .command('expo-tokens')
16
+ .description('Expo access tokens used by `eas build --local`');
17
+ group
18
+ .command('list')
19
+ .description('List Expo tokens')
20
+ .option('--project <slug>', 'Only tokens affecting this project')
21
+ .action(async (opts) => {
22
+ await run(async () => {
23
+ const config = await requireLogin();
24
+ const query = opts.project ? `?project=${encodeURIComponent(opts.project)}` : '';
25
+ const { tokens } = await apiRequest(config, `/expo-tokens${query}`, { token: config.token });
26
+ if (tokens.length === 0) {
27
+ console.log(pc.dim('No Expo tokens. Add one with `buildatlas expo-tokens add`.'));
28
+ return;
29
+ }
30
+ for (const row of tokens)
31
+ console.log(describe(row));
32
+ });
33
+ });
34
+ group
35
+ .command('add')
36
+ .description('Store an Expo access token')
37
+ .option('--label <label>', 'What to call it')
38
+ .option('--project <slug>', 'Scope to one project. Omit to make it usable by every project (admin only).')
39
+ .option('--token <token>', 'The token. Omit to be prompted, which keeps it out of your shell history.')
40
+ .action(async (opts) => {
41
+ await run(async () => {
42
+ const config = await requireLogin();
43
+ // Prompting by default is the point: a token passed as an argument ends up
44
+ // in ~/.zsh_history and in the process list of a shared machine.
45
+ const { label, token } = await withPrompter(async (p) => ({
46
+ label: opts.label ?? (await p.ask('Label: ')),
47
+ token: opts.token ?? (await p.ask('Expo access token: ')),
48
+ }));
49
+ if (!label)
50
+ throw new Error('A label is required.');
51
+ if (!token)
52
+ throw new Error('A token is required.');
53
+ const { token: created } = await apiRequest(config, '/expo-tokens', {
54
+ method: 'POST',
55
+ token: config.token,
56
+ body: JSON.stringify({ label, token, project: opts.project }),
57
+ });
58
+ console.log(pc.green('✔'), 'stored');
59
+ console.log(describe({ ...created, projectSlug: opts.project ?? null }));
60
+ if (created.validationError) {
61
+ console.log(pc.yellow('!'), 'Saved, but Expo could not be reached to confirm it. Verify later with', pc.bold(`buildatlas expo-tokens verify ${created.id}`));
62
+ }
63
+ });
64
+ });
65
+ group
66
+ .command('verify <id>')
67
+ .description('Re-check a token against Expo')
68
+ .action(async (id) => {
69
+ await run(async () => {
70
+ const config = await requireLogin();
71
+ const { token, status } = await apiRequest(config, `/expo-tokens/${id}/verify`, { method: 'POST', token: config.token });
72
+ console.log(status === 'valid' ? pc.green('✔ valid') : pc.yellow(`! ${status}`));
73
+ console.log(describe(token));
74
+ });
75
+ });
76
+ group
77
+ .command('remove <id>')
78
+ .description('Delete a token')
79
+ .action(async (id) => {
80
+ await run(async () => {
81
+ const config = await requireLogin();
82
+ await apiRequest(config, `/expo-tokens/${id}`, { method: 'DELETE', token: config.token });
83
+ console.log(pc.green('✔'), 'removed');
84
+ });
85
+ });
86
+ }
87
+ async function requireLogin() {
88
+ const config = await loadConfig();
89
+ if (!config.token)
90
+ throw new Error('Not logged in. Run `buildatlas login` first.');
91
+ return config;
92
+ }
93
+ async function run(fn) {
94
+ try {
95
+ await fn();
96
+ }
97
+ catch (err) {
98
+ const message = err instanceof AtlasApiError ? `${err.message} (${err.code})` : err.message;
99
+ console.error(pc.red('✖'), message);
100
+ process.exitCode = 1;
101
+ }
102
+ }
103
+ //# sourceMappingURL=expo-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expo-tokens.js","sourceRoot":"","sources":["../../src/commands/expo-tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type ProjectShape } from '../project-type.ts';
2
+ import { Command } from 'commander';
3
+ /** The same shape detection the runner uses, read from the local working tree. */
4
+ export declare function readShape(dir: string): Promise<ProjectShape>;
5
+ export declare function registerInitCommand(program: Command): void;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4CpC,kFAAkF;AAClF,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2DlE;AA8DD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2F1D"}
@@ -0,0 +1,204 @@
1
+ import { readFile, readdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ // Local, not from @buildatlas/shared: that is a private workspace package and importing
4
+ // it here produced an ERR_MODULE_NOT_FOUND for everyone who installed from npm, while
5
+ // working perfectly in this repository. See project-type.ts.
6
+ import { DEFAULT_PROFILES, detectProjectType, } from '../project-type.js';
7
+ import { Command } from 'commander';
8
+ import pc from 'picocolors';
9
+ async function exists(path) {
10
+ try {
11
+ await readFile(path);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ async function entriesOf(dir) {
19
+ try {
20
+ return await readdir(dir);
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ /** The same shape detection the runner uses, read from the local working tree. */
27
+ export async function readShape(dir) {
28
+ let hasPackageJson = false;
29
+ let hasExpoDependency = false;
30
+ let hasReactNativeDependency = false;
31
+ try {
32
+ const pkg = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8'));
33
+ hasPackageJson = true;
34
+ const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
35
+ hasExpoDependency = 'expo' in deps;
36
+ hasReactNativeDependency = 'react-native' in deps;
37
+ }
38
+ catch {
39
+ // No package.json: a native project, or not a project at all.
40
+ }
41
+ let hasExpoConfig = false;
42
+ try {
43
+ const appJson = JSON.parse(await readFile(join(dir, 'app.json'), 'utf8'));
44
+ hasExpoConfig = appJson.expo !== undefined;
45
+ }
46
+ catch {
47
+ for (const name of ['app.config.ts', 'app.config.js', 'app.config.mjs', 'app.config.cjs']) {
48
+ if (await exists(join(dir, name))) {
49
+ hasExpoConfig = true;
50
+ break;
51
+ }
52
+ }
53
+ }
54
+ const xcode = (names) => names.some((n) => n.endsWith('.xcodeproj') || n.endsWith('.xcworkspace'));
55
+ const gradle = (names) => names.some((n) => ['settings.gradle', 'settings.gradle.kts', 'build.gradle', 'build.gradle.kts'].includes(n));
56
+ // The Flutter SDK dependency, not merely a pubspec: a plain Dart package has one too,
57
+ // and `flutter build apk` on one fails talking about a missing Android project.
58
+ let hasFlutterPubspec = false;
59
+ try {
60
+ const pubspec = await readFile(join(dir, 'pubspec.yaml'), 'utf8');
61
+ hasFlutterPubspec = /^\s*sdk:\s*flutter\s*$/m.test(pubspec) || /^flutter:\s*$/m.test(pubspec);
62
+ }
63
+ catch {
64
+ // No pubspec. Not a Flutter project as far as detection is concerned.
65
+ }
66
+ const root = await entriesOf(dir);
67
+ return {
68
+ hasPackageJson,
69
+ hasExpoDependency,
70
+ hasReactNativeDependency,
71
+ hasExpoConfig,
72
+ hasFlutterPubspec,
73
+ hasIosDirectory: xcode(await entriesOf(join(dir, 'ios'))),
74
+ hasAndroidDirectory: gradle(await entriesOf(join(dir, 'android'))),
75
+ hasRootXcodeProject: xcode(root),
76
+ hasRootGradle: gradle(root),
77
+ };
78
+ }
79
+ /** The Xcode container and schemes, for filling in a native iOS descriptor. */
80
+ async function iosHints(dir, type) {
81
+ const iosDir = type === 'ios' ? dir : join(dir, 'ios');
82
+ const names = await entriesOf(iosDir);
83
+ const workspace = names.find((n) => n.endsWith('.xcworkspace'));
84
+ if (workspace)
85
+ return { workspace };
86
+ const project = names.find((n) => n.endsWith('.xcodeproj'));
87
+ return project ? { project } : {};
88
+ }
89
+ /**
90
+ * Builds the descriptor.
91
+ *
92
+ * For a native project the profiles are pre-filled with the workspace or project that
93
+ * was found and a `scheme` placeholder, because those are the two things a native build
94
+ * cannot guess safely and the two things someone would otherwise discover from a failed
95
+ * build ten minutes later.
96
+ */
97
+ async function composeConfig(dir, type, fromEas) {
98
+ if (fromEas && Object.keys(fromEas.build ?? {}).length > 0) {
99
+ // Carried across as-is. The profile shape is a superset, so nothing is lost, and
100
+ // rewriting someone's profiles into a house style would be a diff they did not ask
101
+ // for on the file that decides how their app is built.
102
+ return { ...fromEas, projectType: type };
103
+ }
104
+ const config = { projectType: type, build: structuredClone(DEFAULT_PROFILES) };
105
+ if (type === 'ios' || type === 'android') {
106
+ const hints = type === 'ios' ? await iosHints(dir, type) : {};
107
+ for (const profile of Object.values(config.build)) {
108
+ // A single-platform project has no use for the other platform's block, and
109
+ // leaving it in makes the file look like it configures something it does not.
110
+ if (type === 'ios')
111
+ delete profile.android;
112
+ else
113
+ delete profile.ios;
114
+ if (type === 'ios') {
115
+ profile.ios = {
116
+ ...(profile.ios ?? {}),
117
+ ...hints,
118
+ // Named rather than left out: the detected default is the first scheme found,
119
+ // which is a coin toss in a repository with several.
120
+ scheme: 'REPLACE_ME',
121
+ };
122
+ }
123
+ else {
124
+ // `release` suits a project with no flavours. A flavoured project needs the
125
+ // flavour-qualified variant — productionRelease — which is why the command
126
+ // prints how to list them rather than guessing a flavour name.
127
+ profile.android = { ...(profile.android ?? {}), variant: 'release' };
128
+ }
129
+ }
130
+ }
131
+ return config;
132
+ }
133
+ export function registerInitCommand(program) {
134
+ program
135
+ .command('init')
136
+ .description('Write a buildatlas.json for this project (optional — defaults work without one)')
137
+ .option('-d, --dir <path>', 'Project directory', process.cwd())
138
+ .option('-f, --force', 'Overwrite an existing buildatlas.json')
139
+ .option('--type <type>', 'Force the project type: expo, react-native, ios, android')
140
+ .action(async (opts) => {
141
+ const dir = opts.dir;
142
+ const target = join(dir, 'buildatlas.json');
143
+ if ((await exists(target)) && !opts.force) {
144
+ console.log(`${pc.yellow('!')} ${pc.bold('buildatlas.json')} already exists. Pass --force to replace it.`);
145
+ return;
146
+ }
147
+ const shape = await readShape(dir);
148
+ let type;
149
+ let reason;
150
+ if (opts.type) {
151
+ const valid = ['expo', 'react-native', 'ios', 'android'];
152
+ if (!valid.includes(opts.type)) {
153
+ throw new Error(`--type must be one of ${valid.join(', ')}`);
154
+ }
155
+ type = opts.type;
156
+ reason = 'from --type';
157
+ }
158
+ else {
159
+ const detected = detectProjectType(shape);
160
+ type = detected.type;
161
+ reason = detected.reason;
162
+ }
163
+ // An existing eas.json is converted rather than ignored. Someone running this in a
164
+ // migrated project wants their profiles, not a fresh set of defaults that quietly
165
+ // builds something else.
166
+ // Parsed, not validated. Validation belongs to the worker, which has the schema;
167
+ // this only needs to carry profiles across, and refusing to convert a config the
168
+ // worker would accept would be worse than passing it through unexamined.
169
+ let fromEas;
170
+ try {
171
+ fromEas = JSON.parse(await readFile(join(dir, 'eas.json'), 'utf8'));
172
+ }
173
+ catch (err) {
174
+ // A malformed eas.json is worth saying out loud; a missing one is not.
175
+ if (await exists(join(dir, 'eas.json'))) {
176
+ console.log(`${pc.yellow('!')} could not read eas.json: ${err.message}`);
177
+ }
178
+ }
179
+ const config = await composeConfig(dir, type, fromEas);
180
+ await writeFile(target, `${JSON.stringify(config, null, 2)}\n`);
181
+ console.log(`${pc.green('✔')} wrote ${pc.bold('buildatlas.json')}`);
182
+ console.log(` project type: ${pc.bold(type)} ${pc.dim(`(${reason})`)}`);
183
+ console.log(` profiles: ${Object.keys(config.build).join(', ')} ${fromEas ? pc.dim('(carried over from eas.json)') : pc.dim('(the built-in defaults)')}`);
184
+ if (type === 'ios') {
185
+ console.log(`\n${pc.yellow('!')} Replace ${pc.bold('"scheme": "REPLACE_ME"')} with your Xcode scheme.`);
186
+ console.log(pc.dim(' Names: xcodebuild -list'));
187
+ console.log(pc.dim(' It must be a *shared* scheme — Xcode → Manage Schemes → Shared — or it does not\n' +
188
+ ' exist in the fresh clone the runner builds from.'));
189
+ }
190
+ if (type === 'android') {
191
+ console.log(`\n${pc.dim('If the project has product flavours, set the flavour-qualified variant')}`);
192
+ console.log(pc.dim(' e.g. "variant": "productionRelease". Names: ./gradlew tasks --all | grep assemble'));
193
+ }
194
+ if (type === 'react-native') {
195
+ console.log(`\n${pc.dim('Native directories are committed, so prebuild will not run and your')}`);
196
+ console.log(pc.dim(' hand-edited native files are left alone.'));
197
+ }
198
+ console.log(`\n${pc.dim('Reference:')} docs/build-config.md`);
199
+ if (type === 'ios' || type === 'android') {
200
+ console.log(pc.dim('Native projects: docs/native-projects.md'));
201
+ }
202
+ });
203
+ }
204
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Command } from 'commander';
2
+ /**
3
+ * What we can work out from the app itself.
4
+ *
5
+ * Every field a project needs is already sitting in app.json — the slug, both
6
+ * platform identifiers, and the EAS project id that `eas init` wrote. Asking a
7
+ * person to copy four values into a web form is how they end up mistyping the EAS
8
+ * id and then debugging a build failure.
9
+ */
10
+ export declare function registerProjectCommands(program: Command): void;
11
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/commands/projects.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBzC;;;;;;;GAOG;AAEH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4K9D"}