eas-cli 16.23.0 → 16.23.1

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.
@@ -1,129 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatScriptCommand = exports.initializeGitRepositoryAsync = exports.mergeReadmeAsync = exports.copyProjectTemplatesAsync = exports.updatePackageJsonAsync = exports.generateEasConfigAsync = exports.generateAppConfigAsync = exports.generateConfigFilesAsync = exports.stripInvalidCharactersForBundleIdentifier = exports.createProjectAsync = exports.getAccountChoices = exports.installProjectDependenciesAsync = exports.cloneTemplateAsync = exports.promptForTargetDirectoryAsync = void 0;
3
+ exports.generateProjectFilesAsync = exports.createProjectAsync = exports.generateConfigsAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const eas_json_1 = require("@expo/eas-json");
5
+ const core_1 = require("@oclif/core");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
7
  const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
9
- const path_1 = tslib_1.__importDefault(require("path"));
10
- const ts_deepmerge_1 = tslib_1.__importDefault(require("ts-deepmerge"));
11
- const api_1 = require("../../api");
12
8
  const url_1 = require("../../build/utils/url");
13
9
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
14
- const generated_1 = require("../../graphql/generated");
10
+ const commands_1 = require("../../commandUtils/new/commands");
11
+ const configs_1 = require("../../commandUtils/new/configs");
12
+ const projectFiles_1 = require("../../commandUtils/new/projectFiles");
15
13
  const AppMutation_1 = require("../../graphql/mutations/AppMutation");
16
14
  const AppQuery_1 = require("../../graphql/queries/AppQuery");
17
15
  const log_1 = tslib_1.__importStar(require("../../log"));
18
- const git_1 = require("../../onboarding/git");
19
16
  const installDependencies_1 = require("../../onboarding/installDependencies");
20
- const runCommand_1 = require("../../onboarding/runCommand");
21
17
  const ora_1 = require("../../ora");
22
18
  const expoConfig_1 = require("../../project/expoConfig");
23
- const fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1 = require("../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync");
24
- const prompts_1 = require("../../prompts");
25
- const User_1 = require("../../user/User");
26
- const easCli_1 = require("../../utils/easCli");
27
- async function promptForTargetDirectoryAsync(targetProjectDirFromArgs) {
28
- log_1.default.log(`🚚 Let's start by cloning the default Expo template project from GitHub and installing dependencies.`);
29
- log_1.default.newLine();
30
- if (targetProjectDirFromArgs) {
31
- return targetProjectDirFromArgs;
32
- }
33
- const result = await (0, prompts_1.promptAsync)({
34
- type: 'text',
35
- name: 'targetProjectDir',
36
- message: 'Where would you like to create your new project directory?',
37
- initial: path_1.default.join(process.cwd(), 'new-expo-project'),
38
- });
39
- return result.targetProjectDir;
40
- }
41
- exports.promptForTargetDirectoryAsync = promptForTargetDirectoryAsync;
42
- async function cloneTemplateAsync(targetProjectDir) {
43
- const githubUsername = 'expo';
44
- const githubRepositoryName = 'expo-template-default';
45
- log_1.default.log(`📂 Cloning the project to ${targetProjectDir}`);
46
- log_1.default.newLine();
47
- const cloneMethod = (await (0, git_1.canAccessRepositoryUsingSshAsync)({
48
- githubUsername,
49
- githubRepositoryName,
50
- }))
51
- ? 'ssh'
52
- : 'https';
53
- log_1.default.log(chalk_1.default.dim(`We detected that ${cloneMethod} is your preferred git clone method`));
54
- log_1.default.newLine();
55
- const { targetProjectDir: finalTargetProjectDirectory } = await (0, git_1.runGitCloneAsync)({
56
- githubUsername,
57
- githubRepositoryName,
58
- targetProjectDir,
59
- cloneMethod,
60
- });
61
- return finalTargetProjectDirectory;
62
- }
63
- exports.cloneTemplateAsync = cloneTemplateAsync;
64
- async function installProjectDependenciesAsync(projectDir) {
65
- const packageManager = await (0, installDependencies_1.promptForPackageManagerAsync)();
66
- await (0, installDependencies_1.installDependenciesAsync)({
67
- projectDir,
68
- packageManager,
69
- });
70
- const dependencies = ['expo-updates', '@expo/metro-runtime'];
71
- for (const dependency of dependencies) {
72
- await (0, runCommand_1.runCommandAsync)({
73
- cwd: projectDir,
74
- command: 'npx',
75
- args: ['expo', 'install', dependency],
76
- });
77
- }
78
- return packageManager;
79
- }
80
- exports.installProjectDependenciesAsync = installProjectDependenciesAsync;
81
- function getAccountChoices(actor, namesWithSufficientPermissions) {
82
- const sortedAccounts = actor.accounts.sort((a, _b) => actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0);
83
- return sortedAccounts.map(account => {
84
- const isPersonalAccount = actor.__typename === 'User' && account.name === actor.username;
85
- const accountDisplayName = isPersonalAccount
86
- ? `${account.name} (personal account)`
87
- : account.name;
88
- const disabled = !namesWithSufficientPermissions.has(account.name);
89
- return {
90
- title: accountDisplayName,
91
- value: { name: account.name },
92
- ...(disabled && {
93
- disabled: true,
94
- description: 'You do not have the required permissions to create projects on this account.',
95
- }),
96
- };
19
+ async function generateConfigsAsync(args, actor, graphqlClient) {
20
+ const projectAccount = await (0, configs_1.promptForProjectAccountAsync)(actor);
21
+ const { projectName, projectDirectory } = await (0, configs_1.generateProjectConfigAsync)(actor, args.path, {
22
+ graphqlClient,
23
+ projectAccount,
97
24
  });
25
+ return {
26
+ projectAccount,
27
+ projectDirectory,
28
+ projectName,
29
+ };
98
30
  }
99
- exports.getAccountChoices = getAccountChoices;
100
- async function createProjectAsync(graphqlClient, actor, projectDir) {
101
- const allAccounts = actor.accounts;
102
- const accountNamesWhereUserHasSufficientPermissionsToCreateApp = new Set(allAccounts
103
- .filter(a => a.users.find(it => it.actor.id === actor.id)?.role !== generated_1.Role.ViewOnly)
104
- .map(it => it.name));
105
- let accountName = allAccounts[0].name;
106
- if (allAccounts.length > 1) {
107
- const choices = getAccountChoices(actor, accountNamesWhereUserHasSufficientPermissionsToCreateApp);
108
- accountName = (await (0, prompts_1.promptAsync)({
109
- type: 'select',
110
- name: 'account',
111
- message: 'Which account should own this project?',
112
- choices,
113
- })).account.name;
114
- }
115
- const projectName = (0, User_1.getActorUsername)(actor) + '-app';
116
- const projectFullName = `@${accountName}/${projectName}`;
117
- const existingProjectIdOnServer = await (0, fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1.findProjectIdByAccountNameAndSlugNullableAsync)(graphqlClient, accountName, projectName);
118
- if (existingProjectIdOnServer) {
119
- throw new Error(`Existing project found: ${projectFullName} (ID: ${existingProjectIdOnServer}). Project ID configuration canceled. Re-run the command to select a different account/project.`);
120
- }
121
- if (!accountNamesWhereUserHasSufficientPermissionsToCreateApp.has(accountName)) {
122
- throw new Error(`You don't have permission to create a new project on the ${accountName} account and no matching project already exists on the account.`);
123
- }
124
- const projectDashboardUrl = (0, url_1.getProjectDashboardUrl)(accountName, projectName);
31
+ exports.generateConfigsAsync = generateConfigsAsync;
32
+ async function createProjectAsync({ graphqlClient, actor, projectDirectory, projectAccount, projectName, }) {
33
+ const projectFullName = `@${projectAccount}/${projectName}`;
34
+ const projectDashboardUrl = (0, url_1.getProjectDashboardUrl)(projectAccount, projectName);
125
35
  const projectLink = (0, log_1.link)(projectDashboardUrl, { text: projectFullName });
126
- const account = (0, nullthrows_1.default)(allAccounts.find(a => a.name === accountName));
36
+ const account = (0, nullthrows_1.default)(actor.accounts.find(a => a.name === projectAccount));
127
37
  const spinner = (0, ora_1.ora)(`Creating ${chalk_1.default.bold(projectFullName)}`).start();
128
38
  let projectId;
129
39
  try {
@@ -137,211 +47,72 @@ async function createProjectAsync(graphqlClient, actor, projectDir) {
137
47
  spinner.fail();
138
48
  throw err;
139
49
  }
140
- const exp = await (0, expoConfig_1.getPrivateExpoConfigAsync)(projectDir, { skipPlugins: true });
141
- await (0, expoConfig_1.createOrModifyExpoConfigAsync)(projectDir, {
50
+ const exp = await (0, expoConfig_1.getPrivateExpoConfigAsync)(projectDirectory, { skipPlugins: true });
51
+ await (0, expoConfig_1.createOrModifyExpoConfigAsync)(projectDirectory, {
142
52
  extra: { ...exp.extra, eas: { ...exp.extra?.eas, projectId } },
143
53
  }, { skipSDKVersionRequirement: true });
144
54
  log_1.default.withTick(`Project successfully linked (ID: ${chalk_1.default.bold(projectId)}) (modified app.json)`);
145
55
  return projectId;
146
56
  }
147
57
  exports.createProjectAsync = createProjectAsync;
148
- function stripInvalidCharactersForBundleIdentifier(string) {
149
- return string.replaceAll(/[^A-Za-z0-9]/g, '');
150
- }
151
- exports.stripInvalidCharactersForBundleIdentifier = stripInvalidCharactersForBundleIdentifier;
152
- async function generateConfigFilesAsync(projectDir, app) {
153
- await generateAppConfigAsync(projectDir, app);
154
- await generateEasConfigAsync(projectDir);
155
- await updatePackageJsonAsync(projectDir);
156
- await copyProjectTemplatesAsync(projectDir);
157
- await mergeReadmeAsync(projectDir);
158
- }
159
- exports.generateConfigFilesAsync = generateConfigFilesAsync;
160
- async function generateAppConfigAsync(projectDir, app) {
161
- // Android package name requires each component to start with a lowercase letter.
162
- const isUsernameValidSegment = /^[^a-z]/.test(app.ownerAccount.name);
163
- const userPrefix = isUsernameValidSegment ? 'user' : '';
164
- const isSlugValidSegment = /^[^a-z]/.test(app.slug);
165
- const slugPrefix = isSlugValidSegment ? 'app' : '';
166
- const bundleIdentifier = `com.${userPrefix}${stripInvalidCharactersForBundleIdentifier(app.ownerAccount.name)}.${slugPrefix}${stripInvalidCharactersForBundleIdentifier(app.slug)}`;
167
- const updateUrl = (0, api_1.getEASUpdateURL)(app.id, /* manifestHostOverride */ null);
168
- const { expo: baseExpoConfig } = await fs_extra_1.default.readJson(path_1.default.join(projectDir, 'app.json'));
169
- const expoConfig = {
170
- name: app.name ?? app.slug,
171
- slug: app.slug,
172
- scheme: stripInvalidCharactersForBundleIdentifier(app.name ?? app.slug),
173
- extra: {
174
- eas: {
175
- projectId: app.id,
176
- },
177
- },
178
- owner: app.ownerAccount.name,
179
- updates: {
180
- url: updateUrl,
181
- },
182
- runtimeVersion: {
183
- policy: 'appVersion',
184
- },
185
- ios: {
186
- bundleIdentifier,
187
- },
188
- android: {
189
- package: bundleIdentifier,
190
- },
191
- };
192
- const mergedConfig = (0, ts_deepmerge_1.default)(baseExpoConfig, expoConfig);
193
- const appJsonPath = path_1.default.join(projectDir, 'app.json');
194
- await fs_extra_1.default.writeJson(appJsonPath, { expo: mergedConfig }, { spaces: 2 });
195
- log_1.default.withTick(`Generated ${chalk_1.default.bold('app.json')}. ${(0, log_1.learnMore)('https://docs.expo.dev/versions/latest/config/app/')}`);
196
- log_1.default.log();
197
- }
198
- exports.generateAppConfigAsync = generateAppConfigAsync;
199
- async function generateEasConfigAsync(projectDir) {
200
- const easBuildGitHubConfig = {
201
- android: {
202
- image: 'latest',
203
- },
204
- ios: {
205
- image: 'latest',
206
- },
207
- };
208
- const easJson = {
209
- cli: {
210
- version: `>= ${easCli_1.easCliVersion}`,
211
- appVersionSource: eas_json_1.AppVersionSource.REMOTE,
212
- },
213
- build: {
214
- development: {
215
- developmentClient: true,
216
- distribution: 'internal',
217
- ...easBuildGitHubConfig,
218
- },
219
- 'development-simulator': {
220
- extends: 'development',
221
- ios: {
222
- simulator: true,
223
- },
224
- },
225
- preview: {
226
- distribution: 'internal',
227
- channel: 'main',
228
- ...easBuildGitHubConfig,
229
- },
230
- production: {
231
- channel: 'production',
232
- autoIncrement: true,
233
- ...easBuildGitHubConfig,
234
- },
235
- },
236
- submit: {
237
- production: {},
238
- },
239
- };
240
- const easJsonPath = path_1.default.join(projectDir, 'eas.json');
241
- await fs_extra_1.default.writeJson(easJsonPath, easJson, { spaces: 2 });
242
- log_1.default.withTick(`Generated ${chalk_1.default.bold('eas.json')}. ${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/eas-json/')}`);
243
- log_1.default.log();
244
- }
245
- exports.generateEasConfigAsync = generateEasConfigAsync;
246
- async function updatePackageJsonAsync(projectDir) {
247
- const packageJsonPath = path_1.default.join(projectDir, 'package.json');
248
- const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
249
- if (!packageJson.scripts) {
250
- packageJson.scripts = {};
251
- }
252
- packageJson.scripts.preview = 'npx eas-cli@latest workflow:run publish-preview-update.yml';
253
- packageJson.scripts['development-builds'] =
254
- 'npx eas-cli@latest workflow:run create-development-builds.yml';
255
- packageJson.scripts.deploy = 'npx eas-cli@latest workflow:run deploy-to-production.yml';
256
- await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
257
- log_1.default.withTick('Updated package.json with scripts');
258
- log_1.default.log();
259
- }
260
- exports.updatePackageJsonAsync = updatePackageJsonAsync;
261
- async function copyProjectTemplatesAsync(projectDir) {
262
- const templatesSourceDir = path_1.default.join(__dirname, 'templates', '.eas', 'workflows');
263
- const easWorkflowsTargetDir = path_1.default.join(projectDir, '.eas', 'workflows');
264
- await fs_extra_1.default.copy(templatesSourceDir, easWorkflowsTargetDir, {
265
- overwrite: true,
266
- errorOnExist: false,
267
- });
268
- log_1.default.withTick('Created EAS workflow files');
269
- log_1.default.log();
58
+ async function generateProjectFilesAsync(projectDir, app, packageManager) {
59
+ await (0, projectFiles_1.generateAppConfigAsync)(projectDir, app);
60
+ await (0, projectFiles_1.generateEasConfigAsync)(projectDir);
61
+ await (0, projectFiles_1.updatePackageJsonAsync)(projectDir);
62
+ await (0, projectFiles_1.copyProjectTemplatesAsync)(projectDir);
63
+ await (0, projectFiles_1.updateReadmeAsync)(projectDir, packageManager);
270
64
  }
271
- exports.copyProjectTemplatesAsync = copyProjectTemplatesAsync;
272
- async function mergeReadmeAsync(projectDir) {
273
- const readmeTemplatePath = path_1.default.join(__dirname, 'templates', 'readme-additions.md');
274
- const projectReadmePath = path_1.default.join(projectDir, 'README.md');
275
- const readmeAdditions = await fs_extra_1.default.readFile(readmeTemplatePath, 'utf8');
276
- const existingReadme = await fs_extra_1.default.readFile(projectReadmePath, 'utf8');
277
- const targetSection = '## Get a fresh project';
278
- const sectionIndex = existingReadme.indexOf(targetSection);
279
- let mergedReadme;
280
- if (sectionIndex !== -1) {
281
- // Insert before "## Get a fresh project" section
282
- const beforeSection = existingReadme.substring(0, sectionIndex).trim();
283
- const afterSection = existingReadme.substring(sectionIndex);
284
- mergedReadme = beforeSection + '\n\n' + readmeAdditions.trim() + '\n\n' + afterSection;
285
- }
286
- else {
287
- // Append to the end if section doesn't exist
288
- mergedReadme = existingReadme.trim() + '\n\n' + readmeAdditions.trim() + '\n';
289
- }
290
- await fs_extra_1.default.writeFile(projectReadmePath, mergedReadme);
291
- log_1.default.withTick('Updated README.md with EAS configuration details');
292
- log_1.default.log();
293
- }
294
- exports.mergeReadmeAsync = mergeReadmeAsync;
295
- async function initializeGitRepositoryAsync(projectDir) {
296
- await fs_extra_1.default.remove(path_1.default.join(projectDir, '.git'));
297
- const commands = [['init'], ['add', '.'], ['commit', '-m', 'Initial commit']];
298
- for (const args of commands) {
299
- await (0, runCommand_1.runCommandAsync)({
300
- cwd: projectDir,
301
- command: 'git',
302
- args,
303
- });
304
- log_1.default.log();
305
- }
306
- }
307
- exports.initializeGitRepositoryAsync = initializeGitRepositoryAsync;
308
- const formatScriptCommand = (script, packageManager) => {
309
- if (packageManager === 'npm') {
310
- return `npm run ${script}`;
311
- }
312
- return `${packageManager} ${script}`;
313
- };
314
- exports.formatScriptCommand = formatScriptCommand;
65
+ exports.generateProjectFilesAsync = generateProjectFilesAsync;
315
66
  class New extends EasCommand_1.default {
316
67
  static aliases = ['new'];
317
- static description = "create a new project set up with Expo's services.";
318
- static flags = {};
68
+ static description = 'Create a new project configured with Expo Application Services (EAS)';
69
+ static args = [
70
+ {
71
+ name: 'path',
72
+ description: 'Path to create the project (defaults to current directory)',
73
+ required: false,
74
+ },
75
+ ];
76
+ static flags = {
77
+ 'package-manager': core_1.Flags.enum({
78
+ char: 'p',
79
+ description: 'Package manager to use for installing dependencies',
80
+ options: [...installDependencies_1.PACKAGE_MANAGERS],
81
+ default: 'npm',
82
+ }),
83
+ };
319
84
  static hidden = true;
320
- static args = [{ name: 'TARGET_PROJECT_DIRECTORY' }];
321
85
  static contextDefinition = {
322
86
  ...this.ContextOptions.LoggedIn,
323
87
  };
324
88
  async runAsync() {
325
- const { args } = await this.parse(New);
89
+ const { args, flags } = await this.parse(New);
326
90
  const { loggedIn: { actor, graphqlClient }, } = await this.getContextAsync(New, { nonInteractive: false });
327
91
  if (actor.__typename === 'Robot') {
328
92
  throw new Error('This command is not available for robot users. Make sure you are not using a robot token and try again.');
329
93
  }
330
- log_1.default.warn('This command is not yet implemented. It will create a new project, but it will not be fully configured.');
94
+ log_1.default.warn('This command is not yet implemented. It will create a new project, but it may not be fully configured.');
331
95
  log_1.default.log(`👋 Welcome to Expo, ${actor.username}!`);
332
96
  log_1.default.newLine();
333
- const targetProjectDirectory = await promptForTargetDirectoryAsync(args.TARGET_PROJECT_DIRECTORY);
334
- const projectDirectory = await cloneTemplateAsync(targetProjectDirectory);
335
- const packageManager = await installProjectDependenciesAsync(projectDirectory);
336
- const projectId = await createProjectAsync(graphqlClient, actor, projectDirectory);
97
+ const { projectName, projectDirectory: targetProjectDirectory, projectAccount, } = await generateConfigsAsync(args, actor, graphqlClient);
98
+ const projectDirectory = await (0, commands_1.cloneTemplateAsync)(targetProjectDirectory);
99
+ const packageManager = flags['package-manager'];
100
+ await (0, commands_1.installProjectDependenciesAsync)(projectDirectory, packageManager);
101
+ const projectId = await createProjectAsync({
102
+ projectDirectory,
103
+ projectAccount,
104
+ projectName,
105
+ actor,
106
+ graphqlClient,
107
+ });
337
108
  const app = await AppQuery_1.AppQuery.byIdAsync(graphqlClient, projectId);
338
- await generateConfigFilesAsync(projectDirectory, app);
339
- await initializeGitRepositoryAsync(projectDirectory);
109
+ await generateProjectFilesAsync(projectDirectory, app, packageManager);
110
+ await (0, commands_1.initializeGitRepositoryAsync)(projectDirectory);
340
111
  log_1.default.log('🎉 We finished creating your new project.');
341
112
  log_1.default.log('Next steps:');
342
113
  log_1.default.withInfo(`Run \`cd ${projectDirectory}\` to navigate to your project.`);
343
- log_1.default.withInfo(`Run \`${(0, exports.formatScriptCommand)('preview', packageManager)}\` to create a preview build on EAS. ${(0, log_1.learnMore)('https://docs.expo.dev/eas/workflows/examples/publish-preview-update/')}`);
344
- log_1.default.withInfo(`Run \`${(0, exports.formatScriptCommand)('start', packageManager)}\` to start developing locally. ${(0, log_1.learnMore)('https://docs.expo.dev/get-started/start-developing/')}`);
114
+ log_1.default.withInfo(`Run \`${packageManager} run preview\` to create a preview build on EAS. ${(0, log_1.learnMore)('https://docs.expo.dev/eas/workflows/examples/publish-preview-update/')}`);
115
+ log_1.default.withInfo(`Run \`${packageManager} run start\` to start developing locally. ${(0, log_1.learnMore)('https://docs.expo.dev/get-started/start-developing/')}`);
345
116
  log_1.default.withInfo(`See the README.md for more information about your project.`);
346
117
  log_1.default.newLine();
347
118
  }
@@ -1,6 +1,8 @@
1
- export type PackageManager = 'npm' | 'yarn' | 'pnpm';
1
+ export declare const PACKAGE_MANAGERS: readonly ["bun", "npm", "pnpm", "yarn"];
2
+ export type PackageManager = (typeof PACKAGE_MANAGERS)[number];
2
3
  export declare function promptForPackageManagerAsync(): Promise<PackageManager>;
3
- export declare function installDependenciesAsync({ projectDir, packageManager, }: {
4
+ export declare function installDependenciesAsync({ outputLevel, projectDir, packageManager, }: {
5
+ outputLevel?: 'default' | 'none';
4
6
  projectDir: string;
5
7
  packageManager?: PackageManager;
6
8
  }): Promise<void>;
@@ -1,17 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.installDependenciesAsync = exports.promptForPackageManagerAsync = void 0;
3
+ exports.installDependenciesAsync = exports.promptForPackageManagerAsync = exports.PACKAGE_MANAGERS = void 0;
4
4
  const runCommand_1 = require("./runCommand");
5
5
  const prompts_1 = require("../prompts");
6
+ exports.PACKAGE_MANAGERS = ['bun', 'npm', 'pnpm', 'yarn'];
6
7
  async function promptForPackageManagerAsync() {
7
- return await (0, prompts_1.selectAsync)('Which package manager would you like to use?', [
8
- { title: 'npm', value: 'npm' },
9
- { title: 'Yarn', value: 'yarn' },
10
- { title: 'pnpm', value: 'pnpm' },
11
- ], { initial: 'npm' });
8
+ return await (0, prompts_1.selectAsync)('Which package manager would you like to use?', ['bun', 'npm', 'pnpm', 'yarn'].map(manager => ({ title: manager, value: manager })), { initial: 'npm' });
12
9
  }
13
10
  exports.promptForPackageManagerAsync = promptForPackageManagerAsync;
14
- async function installDependenciesAsync({ projectDir, packageManager = 'npm', }) {
11
+ async function installDependenciesAsync({ outputLevel = 'default', projectDir, packageManager = 'npm', }) {
15
12
  await (0, runCommand_1.runCommandAsync)({
16
13
  command: packageManager,
17
14
  args: ['install'],
@@ -23,6 +20,7 @@ async function installDependenciesAsync({ projectDir, packageManager = 'npm', })
23
20
  !line.includes('has been moved') &&
24
21
  !(line === packageManager));
25
22
  },
23
+ showOutput: outputLevel !== 'none',
26
24
  });
27
25
  }
28
26
  exports.installDependenciesAsync = installDependenciesAsync;
@@ -1,8 +1,9 @@
1
- export declare function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shouldPrintStderrLineAsStdout, showSpinner, }: {
1
+ export declare function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shouldPrintStderrLineAsStdout, showSpinner, showOutput, }: {
2
2
  cwd?: string;
3
3
  args: string[];
4
4
  command: string;
5
5
  shouldShowStderrLine?: (line: string) => boolean;
6
6
  shouldPrintStderrLineAsStdout?: (line: string) => boolean;
7
7
  showSpinner?: boolean;
8
+ showOutput?: boolean;
8
9
  }): Promise<void>;
@@ -6,39 +6,41 @@ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const log_1 = tslib_1.__importDefault(require("../log"));
8
8
  const ora_1 = require("../ora");
9
- async function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shouldPrintStderrLineAsStdout, showSpinner = true, }) {
9
+ async function runCommandAsync({ cwd, args, command, shouldShowStderrLine, shouldPrintStderrLineAsStdout, showSpinner = true, showOutput = true, }) {
10
10
  log_1.default.log(`🏗️ Running ${chalk_1.default.bold(`${command} ${args.join(' ')}`)}...`);
11
11
  let spinner;
12
12
  if (showSpinner) {
13
13
  spinner = (0, ora_1.ora)(`${chalk_1.default.bold(`${command} ${args.join(' ')}`)}`).start();
14
14
  }
15
15
  const spawnPromise = (0, spawn_async_1.default)(command, args, {
16
- stdio: ['inherit', 'pipe', 'pipe'],
16
+ stdio: showOutput ? ['inherit', 'pipe', 'pipe'] : 'ignore',
17
17
  cwd,
18
18
  });
19
- const { child: { stdout, stderr }, } = spawnPromise;
20
- if (!stdout || !stderr) {
21
- throw new Error(`Failed to spawn ${command}`);
22
- }
23
- stdout.on('data', data => {
24
- for (const line of data.toString().trim().split('\n')) {
25
- log_1.default.log(`${chalk_1.default.gray(`[${command}]`)} ${line}`);
19
+ if (showOutput) {
20
+ const { child: { stdout, stderr }, } = spawnPromise;
21
+ if (!stdout || !stderr) {
22
+ throw new Error(`Failed to spawn ${command}`);
26
23
  }
27
- });
28
- stderr.on('data', data => {
29
- for (const line of data.toString().trim().split('\n')) {
30
- if (shouldShowStderrLine && !shouldShowStderrLine(line)) {
31
- continue;
32
- }
33
- const log = `${chalk_1.default.gray(`[${command}]`)} ${line}`;
34
- if (shouldPrintStderrLineAsStdout?.(line)) {
35
- log_1.default.log(log);
24
+ stdout.on('data', data => {
25
+ for (const line of data.toString().trim().split('\n')) {
26
+ log_1.default.log(`${chalk_1.default.gray(`[${command}]`)} ${line}`);
36
27
  }
37
- else {
38
- log_1.default.warn(`${chalk_1.default.gray(`[${command}]`)} ${line}`);
28
+ });
29
+ stderr.on('data', data => {
30
+ for (const line of data.toString().trim().split('\n')) {
31
+ if (shouldShowStderrLine && !shouldShowStderrLine(line)) {
32
+ continue;
33
+ }
34
+ const log = `${chalk_1.default.gray(`[${command}]`)} ${line}`;
35
+ if (shouldPrintStderrLineAsStdout?.(line)) {
36
+ log_1.default.log(log);
37
+ }
38
+ else {
39
+ log_1.default.warn(`${chalk_1.default.gray(`[${command}]`)} ${line}`);
40
+ }
39
41
  }
40
- }
41
- });
42
+ });
43
+ }
42
44
  try {
43
45
  await spawnPromise;
44
46
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "16.23.0",
2
+ "version": "16.23.1",
3
3
  "commands": {
4
4
  "analytics": {
5
5
  "id": "analytics",
@@ -2998,7 +2998,7 @@
2998
2998
  },
2999
2999
  "project:new": {
3000
3000
  "id": "project:new",
3001
- "description": "create a new project set up with Expo's services.",
3001
+ "description": "Create a new project configured with Expo Application Services (EAS)",
3002
3002
  "strict": true,
3003
3003
  "pluginName": "eas-cli",
3004
3004
  "pluginAlias": "eas-cli",
@@ -3007,10 +3007,28 @@
3007
3007
  "aliases": [
3008
3008
  "new"
3009
3009
  ],
3010
- "flags": {},
3010
+ "flags": {
3011
+ "package-manager": {
3012
+ "name": "package-manager",
3013
+ "type": "option",
3014
+ "char": "p",
3015
+ "description": "Package manager to use for installing dependencies",
3016
+ "helpValue": "(bun|npm|pnpm|yarn)",
3017
+ "multiple": false,
3018
+ "options": [
3019
+ "bun",
3020
+ "npm",
3021
+ "pnpm",
3022
+ "yarn"
3023
+ ],
3024
+ "default": "npm"
3025
+ }
3026
+ },
3011
3027
  "args": {
3012
- "TARGET_PROJECT_DIRECTORY": {
3013
- "name": "TARGET_PROJECT_DIRECTORY"
3028
+ "path": {
3029
+ "name": "path",
3030
+ "description": "Path to create the project (defaults to current directory)",
3031
+ "required": false
3014
3032
  }
3015
3033
  },
3016
3034
  "contextDefinition": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eas-cli",
3
3
  "description": "EAS command line tool",
4
- "version": "16.23.0",
4
+ "version": "16.23.1",
5
5
  "author": "Expo <support@expo.dev>",
6
6
  "bin": {
7
7
  "eas": "./bin/run"
@@ -226,7 +226,7 @@
226
226
  "prepack": "yarn rebuild && node ./scripts/prepack.js",
227
227
  "rebuild": "rimraf build && yarn build",
228
228
  "pretarball-ci": "./scripts/pretarball-ci.sh",
229
- "build": "tsc --project tsconfig.build.json",
229
+ "build": "tsc --project tsconfig.build.json && yarn copy-new-templates",
230
230
  "build-allow-unused": "tsc --project tsconfig.allowUnused.json",
231
231
  "watch": "yarn build --watch --preserveWatchOutput",
232
232
  "watch-allow-unused": "yarn build-allow-unused --watch --preserveWatchOutput",
@@ -235,11 +235,12 @@
235
235
  "version": "yarn oclif readme && node scripts/patch-readme && git add README.md",
236
236
  "generate-graphql-code": "graphql-codegen --config graphql-codegen.yml",
237
237
  "verify-graphql-code": "./scripts/verify-graphql.sh",
238
- "clean": "rimraf dist build tmp node_modules yarn-error.log"
238
+ "clean": "rimraf dist build tmp node_modules yarn-error.log",
239
+ "copy-new-templates": "rimraf build/commandUtils/new/templates && mkdir -p build/commandUtils/new && cp -r src/commandUtils/new/templates build/commandUtils/new"
239
240
  },
240
241
  "volta": {
241
242
  "node": "20.11.0",
242
243
  "yarn": "1.22.21"
243
244
  },
244
- "gitHead": "10ec54345a292a2f4612e8100005b93ff5eb6a64"
245
+ "gitHead": "322082c28b1dfea8a809c725c5952ec7666e8e55"
245
246
  }