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.
- package/README.md +85 -85
- package/build/commandUtils/new/commands.d.ts +4 -0
- package/build/commandUtils/new/commands.js +61 -0
- package/build/commandUtils/new/configs.d.ts +25 -0
- package/build/commandUtils/new/configs.js +136 -0
- package/build/commandUtils/new/projectFiles.d.ts +8 -0
- package/build/commandUtils/new/projectFiles.js +167 -0
- package/build/commandUtils/new/templates/.eas/workflows/create-development-builds.yml +21 -0
- package/build/commandUtils/new/templates/.eas/workflows/deploy-to-production.yml +68 -0
- package/build/commandUtils/new/templates/.eas/workflows/publish-preview-update.yml +12 -0
- package/build/commandUtils/new/templates/readme-additions.md +36 -0
- package/build/commands/project/new.d.ts +21 -17
- package/build/commands/project/new.js +62 -291
- package/build/onboarding/installDependencies.d.ts +4 -2
- package/build/onboarding/installDependencies.js +5 -7
- package/build/onboarding/runCommand.d.ts +2 -1
- package/build/onboarding/runCommand.js +24 -22
- package/oclif.manifest.json +23 -5
- package/package.json +5 -4
|
@@ -1,129 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateProjectFilesAsync = exports.createProjectAsync = exports.generateConfigsAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const
|
|
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
|
|
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
|
-
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
100
|
-
async function createProjectAsync(graphqlClient, actor,
|
|
101
|
-
const
|
|
102
|
-
const
|
|
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)(
|
|
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)(
|
|
141
|
-
await (0, expoConfig_1.createOrModifyExpoConfigAsync)(
|
|
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
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
await
|
|
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.
|
|
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 =
|
|
318
|
-
static
|
|
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
|
|
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
|
|
334
|
-
const projectDirectory = await cloneTemplateAsync(targetProjectDirectory);
|
|
335
|
-
const packageManager =
|
|
336
|
-
|
|
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
|
|
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 \`${
|
|
344
|
-
log_1.default.withInfo(`Run \`${
|
|
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
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "16.23.
|
|
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": "
|
|
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
|
-
"
|
|
3013
|
-
"name": "
|
|
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.
|
|
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": "
|
|
245
|
+
"gitHead": "322082c28b1dfea8a809c725c5952ec7666e8e55"
|
|
245
246
|
}
|