eas-cli 16.22.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 +208 -207
- package/build/build/android/graphql.js +1 -2
- package/build/build/evaluateConfigWithEnvVarsAsync.js +5 -11
- package/build/build/ios/graphql.js +1 -2
- package/build/build/utils/environment.d.ts +1 -4
- package/build/build/utils/environment.js +7 -24
- package/build/commandUtils/EasCommand.d.ts +1 -2
- package/build/commandUtils/context/ContextField.d.ts +1 -2
- package/build/commandUtils/context/contextUtils/loadServerSideEnvironmentVariablesAsync.d.ts +1 -2
- package/build/commandUtils/context/contextUtils/loadServerSideEnvironmentVariablesAsync.js +3 -8
- package/build/commandUtils/flags.d.ts +3 -5
- package/build/commandUtils/flags.js +8 -22
- 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/build/resign.d.ts +2 -3
- package/build/commands/deploy/index.d.ts +1 -2
- package/build/commands/env/create.d.ts +1 -2
- package/build/commands/env/create.js +12 -14
- package/build/commands/env/delete.d.ts +1 -2
- package/build/commands/env/delete.js +2 -6
- package/build/commands/env/exec.js +6 -7
- package/build/commands/env/get.d.ts +1 -2
- package/build/commands/env/get.js +4 -6
- package/build/commands/env/list.d.ts +1 -2
- package/build/commands/env/list.js +8 -6
- package/build/commands/env/pull.d.ts +1 -1
- package/build/commands/env/pull.js +8 -8
- package/build/commands/env/push.d.ts +6 -4
- package/build/commands/env/push.js +42 -30
- package/build/commands/env/update.d.ts +2 -3
- package/build/commands/env/update.js +7 -8
- package/build/commands/fingerprint/compare.d.ts +1 -2
- package/build/commands/fingerprint/compare.js +1 -1
- package/build/commands/fingerprint/generate.d.ts +1 -2
- package/build/commands/fingerprint/generate.js +1 -1
- package/build/commands/project/new.d.ts +21 -17
- package/build/commands/project/new.js +62 -291
- package/build/commands/update/configure.d.ts +1 -1
- package/build/commands/update/configure.js +1 -1
- package/build/commands/update/index.d.ts +1 -2
- package/build/commands/update/index.js +1 -1
- package/build/graphql/generated.d.ts +14 -0
- package/build/graphql/queries/EnvironmentVariablesQuery.d.ts +6 -6
- package/build/graphql/queries/EnvironmentVariablesQuery.js +15 -0
- 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/build/utils/prompts.d.ts +8 -5
- package/build/utils/prompts.js +69 -10
- package/build/utils/variableUtils.d.ts +1 -3
- package/build/utils/variableUtils.js +1 -6
- package/build/worker/assets.d.ts +1 -2
- package/oclif.manifest.json +58 -114
- package/package.json +7 -6
|
@@ -4,7 +4,6 @@ exports.transformJob = void 0;
|
|
|
4
4
|
const eas_build_job_1 = require("@expo/eas-build-job");
|
|
5
5
|
const generated_1 = require("../../graphql/generated");
|
|
6
6
|
const graphql_1 = require("../graphql");
|
|
7
|
-
const environment_1 = require("../utils/environment");
|
|
8
7
|
function transformJob(job) {
|
|
9
8
|
return {
|
|
10
9
|
type: (0, graphql_1.transformWorkflow)(job.type),
|
|
@@ -25,7 +24,7 @@ function transformJob(job) {
|
|
|
25
24
|
experimental: job.experimental,
|
|
26
25
|
mode: (0, graphql_1.transformBuildMode)(job.mode),
|
|
27
26
|
customBuildConfig: job.customBuildConfig,
|
|
28
|
-
environment:
|
|
27
|
+
environment: job.environment,
|
|
29
28
|
loggerLevel: job.loggerLevel
|
|
30
29
|
? graphql_1.loggerLevelToGraphQLWorkerLoggerLevel[job.loggerLevel]
|
|
31
30
|
: undefined,
|
|
@@ -23,14 +23,8 @@ async function evaluateConfigWithEnvVarsAsync({ buildProfile, buildProfileName,
|
|
|
23
23
|
}
|
|
24
24
|
exports.evaluateConfigWithEnvVarsAsync = evaluateConfigWithEnvVarsAsync;
|
|
25
25
|
async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClient, projectId, }) {
|
|
26
|
-
const environment = buildProfile.environment
|
|
26
|
+
const environment = buildProfile.environment ??
|
|
27
27
|
resolveSuggestedEnvironmentForBuildProfileConfiguration(buildProfile);
|
|
28
|
-
if (!(0, environment_1.isEnvironment)(environment)) {
|
|
29
|
-
log_1.default.log(`Loaded "env" configuration for the "${buildProfileName}" profile: ${buildProfile.env && Object.keys(buildProfile.env).length > 0
|
|
30
|
-
? Object.keys(buildProfile.env).join(', ')
|
|
31
|
-
: 'no environment variables specified'}. ${(0, log_1.learnMore)('https://docs.expo.dev/build-reference/variables/')}`);
|
|
32
|
-
return { ...buildProfile.env };
|
|
33
|
-
}
|
|
34
28
|
try {
|
|
35
29
|
const environmentVariables = await EnvironmentVariablesQuery_1.EnvironmentVariablesQuery.byAppIdWithSensitiveAsync(graphqlClient, {
|
|
36
30
|
appId: projectId,
|
|
@@ -68,10 +62,10 @@ async function resolveEnvVarsAsync({ buildProfile, buildProfileName, graphqlClie
|
|
|
68
62
|
}
|
|
69
63
|
function resolveSuggestedEnvironmentForBuildProfileConfiguration(buildProfile) {
|
|
70
64
|
const environment = buildProfile.distribution === 'store'
|
|
71
|
-
? environment_1.
|
|
65
|
+
? environment_1.DefaultEnvironment.Production
|
|
72
66
|
: buildProfile.developmentClient
|
|
73
|
-
? environment_1.
|
|
74
|
-
: environment_1.
|
|
75
|
-
log_1.default.log(`Resolved "${environment
|
|
67
|
+
? environment_1.DefaultEnvironment.Development
|
|
68
|
+
: environment_1.DefaultEnvironment.Preview;
|
|
69
|
+
log_1.default.log(`Resolved "${environment}" environment for the build. ${(0, log_1.learnMore)('https://docs.expo.dev/eas/environment-variables/#setting-the-environment-for-your-builds')}`);
|
|
76
70
|
return environment;
|
|
77
71
|
}
|
|
@@ -4,7 +4,6 @@ exports.transformIosSecrets = exports.transformJob = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
|
|
6
6
|
const graphql_1 = require("../graphql");
|
|
7
|
-
const environment_1 = require("../utils/environment");
|
|
8
7
|
function transformJob(job) {
|
|
9
8
|
return {
|
|
10
9
|
type: (0, graphql_1.transformWorkflow)(job.type),
|
|
@@ -26,7 +25,7 @@ function transformJob(job) {
|
|
|
26
25
|
experimental: job.experimental,
|
|
27
26
|
mode: (0, graphql_1.transformBuildMode)(job.mode),
|
|
28
27
|
customBuildConfig: job.customBuildConfig,
|
|
29
|
-
environment:
|
|
28
|
+
environment: job.environment,
|
|
30
29
|
loggerLevel: job.loggerLevel
|
|
31
30
|
? graphql_1.loggerLevelToGraphQLWorkerLoggerLevel[job.loggerLevel]
|
|
32
31
|
: undefined,
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export declare enum EnvironmentVariableEnvironment {
|
|
1
|
+
export declare enum DefaultEnvironment {
|
|
3
2
|
Development = "development",
|
|
4
3
|
Preview = "preview",
|
|
5
4
|
Production = "production"
|
|
6
5
|
}
|
|
7
|
-
export declare function isEnvironment(env: string): env is EnvironmentVariableEnvironment;
|
|
8
|
-
export declare function buildProfileEnvironmentToEnvironment(environment: BuildProfile['environment']): EnvironmentVariableEnvironment | null;
|
|
@@ -1,26 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
})(EnvironmentVariableEnvironment || (exports.EnvironmentVariableEnvironment = EnvironmentVariableEnvironment = {}));
|
|
11
|
-
const BuildProfileEnvironmentToEnvironment = {
|
|
12
|
-
production: EnvironmentVariableEnvironment.Production,
|
|
13
|
-
preview: EnvironmentVariableEnvironment.Preview,
|
|
14
|
-
development: EnvironmentVariableEnvironment.Development,
|
|
15
|
-
};
|
|
16
|
-
function isEnvironment(env) {
|
|
17
|
-
return Object.values(EnvironmentVariableEnvironment).includes(env.toLowerCase());
|
|
18
|
-
}
|
|
19
|
-
exports.isEnvironment = isEnvironment;
|
|
20
|
-
function buildProfileEnvironmentToEnvironment(environment) {
|
|
21
|
-
if (!environment) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
return BuildProfileEnvironmentToEnvironment[environment];
|
|
25
|
-
}
|
|
26
|
-
exports.buildProfileEnvironmentToEnvironment = buildProfileEnvironmentToEnvironment;
|
|
3
|
+
exports.DefaultEnvironment = void 0;
|
|
4
|
+
var DefaultEnvironment;
|
|
5
|
+
(function (DefaultEnvironment) {
|
|
6
|
+
DefaultEnvironment["Development"] = "development";
|
|
7
|
+
DefaultEnvironment["Preview"] = "preview";
|
|
8
|
+
DefaultEnvironment["Production"] = "production";
|
|
9
|
+
})(DefaultEnvironment || (exports.DefaultEnvironment = DefaultEnvironment = {}));
|
|
@@ -12,7 +12,6 @@ import { ProjectIdContextField } from './context/ProjectIdContextField';
|
|
|
12
12
|
import { ServerSideEnvironmentVariablesContextField } from './context/ServerSideEnvironmentVariablesContextField';
|
|
13
13
|
import SessionManagementContextField from './context/SessionManagementContextField';
|
|
14
14
|
import VcsClientContextField from './context/VcsClientContextField';
|
|
15
|
-
import { EnvironmentVariableEnvironment } from '../build/utils/environment';
|
|
16
15
|
import { Client } from '../vcs/vcs';
|
|
17
16
|
export type ContextInput<T extends {
|
|
18
17
|
[name: string]: any;
|
|
@@ -32,7 +31,7 @@ interface BaseGetContextAsyncArgs {
|
|
|
32
31
|
vcsClientOverride?: Client;
|
|
33
32
|
}
|
|
34
33
|
interface GetContextAsyncArgsWithRequiredServerSideEnvironmentArgument extends BaseGetContextAsyncArgs {
|
|
35
|
-
withServerSideEnvironment:
|
|
34
|
+
withServerSideEnvironment: string | null;
|
|
36
35
|
}
|
|
37
36
|
interface GetContextAsyncArgsWithoutServerSideEnvironmentArgument extends BaseGetContextAsyncArgs {
|
|
38
37
|
withServerSideEnvironment?: never;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Analytics } from '../../analytics/AnalyticsManager';
|
|
2
|
-
import { EnvironmentVariableEnvironment } from '../../build/utils/environment';
|
|
3
2
|
import SessionManager from '../../user/SessionManager';
|
|
4
3
|
import { Client } from '../../vcs/vcs';
|
|
5
4
|
export interface ContextOptions {
|
|
@@ -10,7 +9,7 @@ export interface ContextOptions {
|
|
|
10
9
|
/**
|
|
11
10
|
* If specified, env variables from the selected environment will be fetched from the server and used to evaluate the dynamic config.
|
|
12
11
|
*/
|
|
13
|
-
withServerSideEnvironment?:
|
|
12
|
+
withServerSideEnvironment?: string | null;
|
|
14
13
|
}
|
|
15
14
|
export default abstract class ContextField<T> {
|
|
16
15
|
abstract getValueAsync(options: ContextOptions): Promise<T>;
|
package/build/commandUtils/context/contextUtils/loadServerSideEnvironmentVariablesAsync.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ExpoGraphqlClient } from './createGraphqlClient';
|
|
2
|
-
import { EnvironmentVariableEnvironment } from '../../../build/utils/environment';
|
|
3
2
|
export declare function loadServerSideEnvironmentVariablesAsync({ environment, projectId, graphqlClient, }: {
|
|
4
|
-
environment:
|
|
3
|
+
environment: string;
|
|
5
4
|
projectId: string;
|
|
6
5
|
graphqlClient: ExpoGraphqlClient;
|
|
7
6
|
}): Promise<Record<string, string>>;
|
|
@@ -2,14 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadServerSideEnvironmentVariablesAsync = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const environment_1 = require("../../../build/utils/environment");
|
|
6
5
|
const EnvironmentVariablesQuery_1 = require("../../../graphql/queries/EnvironmentVariablesQuery");
|
|
7
6
|
const log_1 = tslib_1.__importDefault(require("../../../log"));
|
|
8
|
-
const cachedServerSideEnvironmentVariables = {
|
|
9
|
-
[environment_1.EnvironmentVariableEnvironment.Development]: null,
|
|
10
|
-
[environment_1.EnvironmentVariableEnvironment.Preview]: null,
|
|
11
|
-
[environment_1.EnvironmentVariableEnvironment.Production]: null,
|
|
12
|
-
};
|
|
7
|
+
const cachedServerSideEnvironmentVariables = {};
|
|
13
8
|
async function loadServerSideEnvironmentVariablesAsync({ environment, projectId, graphqlClient, }) {
|
|
14
9
|
// don't load environment variables if they were already loaded while executing a command
|
|
15
10
|
const cachedEnvVarsForEnvironment = cachedServerSideEnvironmentVariables[environment];
|
|
@@ -24,10 +19,10 @@ async function loadServerSideEnvironmentVariablesAsync({ environment, projectId,
|
|
|
24
19
|
.filter(({ name, value }) => name && value)
|
|
25
20
|
.map(({ name, value }) => [name, value]));
|
|
26
21
|
if (Object.keys(serverEnvVars).length > 0) {
|
|
27
|
-
log_1.default.log(`Environment variables with visibility "Plain text" and "Sensitive" loaded from the "${environment
|
|
22
|
+
log_1.default.log(`Environment variables with visibility "Plain text" and "Sensitive" loaded from the "${environment}" environment on EAS: ${Object.keys(serverEnvVars).join(', ')}.`);
|
|
28
23
|
}
|
|
29
24
|
else {
|
|
30
|
-
log_1.default.log(`No environment variables with visibility "Plain text" and "Sensitive" found for the "${environment
|
|
25
|
+
log_1.default.log(`No environment variables with visibility "Plain text" and "Sensitive" found for the "${environment}" environment on EAS.`);
|
|
31
26
|
}
|
|
32
27
|
log_1.default.newLine();
|
|
33
28
|
cachedServerSideEnvironmentVariables[environment] = serverEnvVars;
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import { EnvironmentVariableEnvironment } from '../build/utils/environment';
|
|
2
1
|
export declare const EasNonInteractiveAndJsonFlags: {
|
|
3
2
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
4
3
|
'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
5
4
|
};
|
|
6
5
|
export declare const EasEnvironmentFlagParameters: {
|
|
7
6
|
description: string;
|
|
8
|
-
options: EnvironmentVariableEnvironment[];
|
|
9
7
|
};
|
|
10
8
|
export declare const EASEnvironmentFlag: {
|
|
11
|
-
environment: import("@oclif/core/lib/interfaces").OptionFlag<
|
|
9
|
+
environment: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
12
10
|
};
|
|
13
11
|
export declare const EASMultiEnvironmentFlag: {
|
|
14
|
-
environment: import("@oclif/core/lib/interfaces").OptionFlag<
|
|
12
|
+
environment: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined>;
|
|
15
13
|
};
|
|
16
14
|
export declare const EASVariableFormatFlag: {
|
|
17
15
|
format: import("@oclif/core/lib/interfaces").OptionFlag<string>;
|
|
@@ -30,5 +28,5 @@ export declare const EasJsonOnlyFlag: {
|
|
|
30
28
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
31
29
|
};
|
|
32
30
|
export declare const EasUpdateEnvironmentFlag: {
|
|
33
|
-
environment: import("@oclif/core/lib/interfaces").OptionFlag<
|
|
31
|
+
environment: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
34
32
|
};
|
|
@@ -2,15 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EasUpdateEnvironmentFlag = exports.EasJsonOnlyFlag = exports.EASNonInteractiveFlag = exports.EASEnvironmentVariableScopeFlag = exports.EASVariableVisibilityFlag = exports.EASVariableFormatFlag = exports.EASMultiEnvironmentFlag = exports.EASEnvironmentFlag = exports.EasEnvironmentFlagParameters = exports.EasNonInteractiveAndJsonFlags = void 0;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
-
const environment_1 = require("../build/utils/environment");
|
|
6
|
-
// NOTE: not exactly true, but, provided mapToLowercase and upperCaseAsync
|
|
7
|
-
// are used in tandem, it saves on unnecessary typying in commands
|
|
8
|
-
async function upperCaseAsync(input) {
|
|
9
|
-
return input.toUpperCase();
|
|
10
|
-
}
|
|
11
|
-
function mapToLowercase(options) {
|
|
12
|
-
return options.map(option => option.toLowerCase());
|
|
13
|
-
}
|
|
14
5
|
exports.EasNonInteractiveAndJsonFlags = {
|
|
15
6
|
json: core_1.Flags.boolean({
|
|
16
7
|
description: 'Enable JSON output, non-JSON messages will be printed to stderr.',
|
|
@@ -21,18 +12,15 @@ exports.EasNonInteractiveAndJsonFlags = {
|
|
|
21
12
|
}),
|
|
22
13
|
};
|
|
23
14
|
exports.EasEnvironmentFlagParameters = {
|
|
24
|
-
description: "Environment variable's environment",
|
|
25
|
-
options: mapToLowercase([
|
|
26
|
-
environment_1.EnvironmentVariableEnvironment.Development,
|
|
27
|
-
environment_1.EnvironmentVariableEnvironment.Preview,
|
|
28
|
-
environment_1.EnvironmentVariableEnvironment.Production,
|
|
29
|
-
]),
|
|
15
|
+
description: "Environment variable's environment, e.g. 'production', 'preview', 'development'",
|
|
30
16
|
};
|
|
31
17
|
exports.EASEnvironmentFlag = {
|
|
32
|
-
environment: core_1.Flags.
|
|
18
|
+
environment: core_1.Flags.string({
|
|
19
|
+
description: "Environment variable's environment, e.g. 'production', 'preview', 'development'",
|
|
20
|
+
}),
|
|
33
21
|
};
|
|
34
22
|
exports.EASMultiEnvironmentFlag = {
|
|
35
|
-
environment: core_1.Flags.
|
|
23
|
+
environment: core_1.Flags.string({
|
|
36
24
|
...exports.EasEnvironmentFlagParameters,
|
|
37
25
|
multiple: true,
|
|
38
26
|
}),
|
|
@@ -68,11 +56,9 @@ exports.EasJsonOnlyFlag = {
|
|
|
68
56
|
}),
|
|
69
57
|
};
|
|
70
58
|
exports.EasUpdateEnvironmentFlag = {
|
|
71
|
-
environment: core_1.Flags.
|
|
72
|
-
description: 'Environment to use for the server-side defined EAS environment variables during command execution.',
|
|
73
|
-
options: mapToLowercase(Object.values(environment_1.EnvironmentVariableEnvironment)),
|
|
74
|
-
parse: upperCaseAsync,
|
|
59
|
+
environment: core_1.Flags.string({
|
|
60
|
+
description: 'Environment to use for the server-side defined EAS environment variables during command execution, e.g. "production", "preview", "development"',
|
|
75
61
|
required: false,
|
|
76
|
-
default:
|
|
62
|
+
default: undefined,
|
|
77
63
|
}),
|
|
78
64
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PackageManager } from '../../onboarding/installDependencies';
|
|
2
|
+
export declare function cloneTemplateAsync(targetProjectDir: string): Promise<string>;
|
|
3
|
+
export declare function installProjectDependenciesAsync(projectDir: string, packageManager: PackageManager): Promise<void>;
|
|
4
|
+
export declare function initializeGitRepositoryAsync(projectDir: string): Promise<void>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initializeGitRepositoryAsync = exports.installProjectDependenciesAsync = exports.cloneTemplateAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
8
|
+
const git_1 = require("../../onboarding/git");
|
|
9
|
+
const installDependencies_1 = require("../../onboarding/installDependencies");
|
|
10
|
+
const runCommand_1 = require("../../onboarding/runCommand");
|
|
11
|
+
async function cloneTemplateAsync(targetProjectDir) {
|
|
12
|
+
const githubUsername = 'expo';
|
|
13
|
+
const githubRepositoryName = 'expo-template-default';
|
|
14
|
+
log_1.default.log(`📂 Cloning the project to ${targetProjectDir}`);
|
|
15
|
+
log_1.default.newLine();
|
|
16
|
+
const cloneMethod = (await (0, git_1.canAccessRepositoryUsingSshAsync)({
|
|
17
|
+
githubUsername,
|
|
18
|
+
githubRepositoryName,
|
|
19
|
+
}))
|
|
20
|
+
? 'ssh'
|
|
21
|
+
: 'https';
|
|
22
|
+
const { targetProjectDir: finalTargetProjectDirectory } = await (0, git_1.runGitCloneAsync)({
|
|
23
|
+
githubUsername,
|
|
24
|
+
githubRepositoryName,
|
|
25
|
+
targetProjectDir,
|
|
26
|
+
cloneMethod,
|
|
27
|
+
});
|
|
28
|
+
return finalTargetProjectDirectory;
|
|
29
|
+
}
|
|
30
|
+
exports.cloneTemplateAsync = cloneTemplateAsync;
|
|
31
|
+
async function installProjectDependenciesAsync(projectDir, packageManager) {
|
|
32
|
+
await (0, installDependencies_1.installDependenciesAsync)({
|
|
33
|
+
outputLevel: 'none',
|
|
34
|
+
projectDir,
|
|
35
|
+
packageManager,
|
|
36
|
+
});
|
|
37
|
+
const dependencies = ['expo-updates', '@expo/metro-runtime'];
|
|
38
|
+
for (const dependency of dependencies) {
|
|
39
|
+
await (0, runCommand_1.runCommandAsync)({
|
|
40
|
+
cwd: projectDir,
|
|
41
|
+
command: 'npx',
|
|
42
|
+
args: ['expo', 'install', dependency],
|
|
43
|
+
showOutput: false,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.installProjectDependenciesAsync = installProjectDependenciesAsync;
|
|
48
|
+
async function initializeGitRepositoryAsync(projectDir) {
|
|
49
|
+
await fs_extra_1.default.remove(path_1.default.join(projectDir, '.git'));
|
|
50
|
+
const commands = [['init'], ['add', '.'], ['commit', '-m', 'Initial commit']];
|
|
51
|
+
for (const args of commands) {
|
|
52
|
+
await (0, runCommand_1.runCommandAsync)({
|
|
53
|
+
cwd: projectDir,
|
|
54
|
+
command: 'git',
|
|
55
|
+
args,
|
|
56
|
+
showOutput: false,
|
|
57
|
+
});
|
|
58
|
+
log_1.default.log();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.initializeGitRepositoryAsync = initializeGitRepositoryAsync;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Choice } from '../../prompts';
|
|
2
|
+
import { Actor } from '../../user/User';
|
|
3
|
+
import { ExpoGraphqlClient } from '../context/contextUtils/createGraphqlClient';
|
|
4
|
+
export declare function generateProjectConfigAsync(actor: Actor, pathArg: string | undefined, options: {
|
|
5
|
+
graphqlClient: ExpoGraphqlClient;
|
|
6
|
+
projectAccount: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
projectName: string;
|
|
9
|
+
projectDirectory: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function promptForProjectAccountAsync(actor: Actor): Promise<string>;
|
|
12
|
+
export declare function getAccountChoices(actor: Actor, permissionsMap?: Map<string, boolean>): Choice[];
|
|
13
|
+
export declare function generateProjectNameVariations(actor: Actor, baseName: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Finds an available project name that doesn't conflict with either:
|
|
16
|
+
* Local filesystem (directory already exists)
|
|
17
|
+
* Remote server (project already exists on Expo)
|
|
18
|
+
*/
|
|
19
|
+
export declare function findAvailableProjectNameAsync(actor: Actor, baseName: string, parentDirectory: string, { graphqlClient, projectAccount, }: {
|
|
20
|
+
graphqlClient: ExpoGraphqlClient;
|
|
21
|
+
projectAccount: string;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
projectName: string;
|
|
24
|
+
projectDirectory: string;
|
|
25
|
+
}>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findAvailableProjectNameAsync = exports.generateProjectNameVariations = exports.getAccountChoices = exports.promptForProjectAccountAsync = exports.generateProjectConfigAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
6
|
+
const nanoid_1 = require("nanoid");
|
|
7
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
+
const generated_1 = require("../../graphql/generated");
|
|
9
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
10
|
+
const fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1 = require("../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync");
|
|
11
|
+
const prompts_1 = require("../../prompts");
|
|
12
|
+
const User_1 = require("../../user/User");
|
|
13
|
+
function validateProjectPath(resolvedPath) {
|
|
14
|
+
const normalizedPath = path_1.default.normalize(resolvedPath);
|
|
15
|
+
// Check for path traversal attempts
|
|
16
|
+
if (normalizedPath.includes('..')) {
|
|
17
|
+
throw new Error(`Invalid project path: "${resolvedPath}". Path traversal is not allowed.`);
|
|
18
|
+
}
|
|
19
|
+
// Ensure we're not trying to create a project in system directories
|
|
20
|
+
const systemDirs = ['/bin', '/sbin', '/etc', '/usr', '/var', '/sys', '/proc', '/dev'];
|
|
21
|
+
const isSystemDir = systemDirs.some(dir => normalizedPath === dir || normalizedPath.startsWith(dir + path_1.default.sep));
|
|
22
|
+
if (isSystemDir) {
|
|
23
|
+
throw new Error(`Invalid project path: "${resolvedPath}". Cannot create projects in system directories.`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function generateProjectConfigAsync(actor, pathArg, options) {
|
|
27
|
+
let baseName = 'new-expo-project';
|
|
28
|
+
let parentDirectory = process.cwd();
|
|
29
|
+
if (pathArg) {
|
|
30
|
+
const resolvedPath = path_1.default.isAbsolute(pathArg) ? pathArg : path_1.default.resolve(process.cwd(), pathArg);
|
|
31
|
+
validateProjectPath(resolvedPath);
|
|
32
|
+
baseName = path_1.default.basename(resolvedPath);
|
|
33
|
+
parentDirectory = path_1.default.dirname(resolvedPath);
|
|
34
|
+
}
|
|
35
|
+
// Find an available name checking both local filesystem and remote server
|
|
36
|
+
const { projectName, projectDirectory } = await findAvailableProjectNameAsync(actor, baseName, parentDirectory, options);
|
|
37
|
+
log_1.default.withInfo(`Using project directory: ${projectDirectory}`);
|
|
38
|
+
return {
|
|
39
|
+
projectName,
|
|
40
|
+
projectDirectory,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
exports.generateProjectConfigAsync = generateProjectConfigAsync;
|
|
44
|
+
function getAccountPermissionsMap(actor) {
|
|
45
|
+
const permissionsMap = new Map();
|
|
46
|
+
for (const account of actor.accounts) {
|
|
47
|
+
const hasPermission = account.users.find(it => it.actor.id === actor.id)?.role !== generated_1.Role.ViewOnly;
|
|
48
|
+
permissionsMap.set(account.name, hasPermission);
|
|
49
|
+
}
|
|
50
|
+
return permissionsMap;
|
|
51
|
+
}
|
|
52
|
+
async function promptForProjectAccountAsync(actor) {
|
|
53
|
+
const permissionsMap = getAccountPermissionsMap(actor);
|
|
54
|
+
// If only one account, use it (if has permissions)
|
|
55
|
+
if (actor.accounts.length === 1) {
|
|
56
|
+
const account = actor.accounts[0];
|
|
57
|
+
if (permissionsMap.get(account.name)) {
|
|
58
|
+
return account.name;
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`You don't have permission to create projects on your only available account (${account.name}).`);
|
|
61
|
+
}
|
|
62
|
+
// Multiple accounts - prompt user to select one with permissions
|
|
63
|
+
return (await (0, prompts_1.promptAsync)({
|
|
64
|
+
type: 'select',
|
|
65
|
+
name: 'account',
|
|
66
|
+
message: 'Which account should own this project?',
|
|
67
|
+
choices: getAccountChoices(actor, permissionsMap),
|
|
68
|
+
})).account.name;
|
|
69
|
+
}
|
|
70
|
+
exports.promptForProjectAccountAsync = promptForProjectAccountAsync;
|
|
71
|
+
function getAccountChoices(actor, permissionsMap) {
|
|
72
|
+
const permissions = permissionsMap ?? getAccountPermissionsMap(actor);
|
|
73
|
+
const sortedAccounts = [...actor.accounts].sort((a, _b) => actor.__typename === 'User' ? (a.name === actor.username ? -1 : 1) : 0);
|
|
74
|
+
return sortedAccounts.map(account => {
|
|
75
|
+
const isPersonalAccount = actor.__typename === 'User' && account.name === actor.username;
|
|
76
|
+
const accountDisplayName = isPersonalAccount
|
|
77
|
+
? `${account.name} (personal account)`
|
|
78
|
+
: account.name;
|
|
79
|
+
const disabled = !permissions.get(account.name);
|
|
80
|
+
return {
|
|
81
|
+
title: accountDisplayName,
|
|
82
|
+
value: { name: account.name },
|
|
83
|
+
...(disabled && {
|
|
84
|
+
disabled: true,
|
|
85
|
+
description: 'You do not have the required permissions to create projects on this account.',
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
exports.getAccountChoices = getAccountChoices;
|
|
91
|
+
function generateProjectNameVariations(actor, baseName) {
|
|
92
|
+
const username = (0, User_1.getActorUsername)(actor);
|
|
93
|
+
const date = new Date().toISOString().split('T')[0];
|
|
94
|
+
return [
|
|
95
|
+
baseName,
|
|
96
|
+
`${baseName}-${username}-${date}`,
|
|
97
|
+
`${baseName}-${username}-${date}-${(0, nanoid_1.nanoid)(6)}`,
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
exports.generateProjectNameVariations = generateProjectNameVariations;
|
|
101
|
+
async function verifyProjectDoesNotExistAsync(graphqlClient, accountName, projectName, { silent = false } = {}) {
|
|
102
|
+
const existingProjectId = await (0, fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync_1.findProjectIdByAccountNameAndSlugNullableAsync)(graphqlClient, accountName, projectName);
|
|
103
|
+
const doesNotExist = existingProjectId === null;
|
|
104
|
+
if (!doesNotExist && !silent) {
|
|
105
|
+
log_1.default.warn(`Project @${accountName}/${projectName} already exists on the server.`);
|
|
106
|
+
}
|
|
107
|
+
return doesNotExist;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Finds an available project name that doesn't conflict with either:
|
|
111
|
+
* Local filesystem (directory already exists)
|
|
112
|
+
* Remote server (project already exists on Expo)
|
|
113
|
+
*/
|
|
114
|
+
async function findAvailableProjectNameAsync(actor, baseName, parentDirectory, { graphqlClient, projectAccount, }) {
|
|
115
|
+
const nameVariations = generateProjectNameVariations(actor, baseName);
|
|
116
|
+
for (let i = 0; i < nameVariations.length; i++) {
|
|
117
|
+
const nameVariation = nameVariations[i];
|
|
118
|
+
const proposedDirectory = path_1.default.join(parentDirectory, nameVariation);
|
|
119
|
+
const usingVariant = i !== 0;
|
|
120
|
+
const localExists = await fs_extra_1.default.pathExists(proposedDirectory);
|
|
121
|
+
if (localExists) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const remoteAvailable = await verifyProjectDoesNotExistAsync(graphqlClient, projectAccount, nameVariation, { silent: usingVariant });
|
|
125
|
+
if (!remoteAvailable) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
log_1.default.withInfo(`Using ${usingVariant ? 'alternate ' : ''}project name: ${nameVariation}`);
|
|
129
|
+
return {
|
|
130
|
+
projectName: nameVariation,
|
|
131
|
+
projectDirectory: proposedDirectory,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
throw new Error(`Unable to find a unique project name for "${baseName}". All generated variations already exist.`);
|
|
135
|
+
}
|
|
136
|
+
exports.findAvailableProjectNameAsync = findAvailableProjectNameAsync;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AppFragment } from '../../graphql/generated';
|
|
2
|
+
import { PackageManager } from '../../onboarding/installDependencies';
|
|
3
|
+
export declare function cleanAndPrefix(_string: string, type: 'user' | 'app' | 'scheme'): string;
|
|
4
|
+
export declare function generateAppConfigAsync(projectDir: string, app: AppFragment): Promise<void>;
|
|
5
|
+
export declare function generateEasConfigAsync(projectDir: string): Promise<void>;
|
|
6
|
+
export declare function updatePackageJsonAsync(projectDir: string): Promise<void>;
|
|
7
|
+
export declare function copyProjectTemplatesAsync(projectDir: string): Promise<void>;
|
|
8
|
+
export declare function updateReadmeAsync(projectDir: string, packageManager: PackageManager): Promise<void>;
|