eas-cli 18.9.1 → 18.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +230 -95
  2. package/build/build/runBuildAndSubmit.d.ts +3 -1
  3. package/build/build/runBuildAndSubmit.js +12 -4
  4. package/build/build/utils/repository.js +15 -3
  5. package/build/build/validateLockfile.d.ts +1 -0
  6. package/build/build/validateLockfile.js +37 -0
  7. package/build/commandUtils/buildFlags.d.ts +1 -0
  8. package/build/commandUtils/buildFlags.js +18 -0
  9. package/build/commandUtils/convex.d.ts +12 -0
  10. package/build/commandUtils/convex.js +77 -0
  11. package/build/commands/build/dev.d.ts +1 -0
  12. package/build/commands/build/dev.js +12 -2
  13. package/build/commands/build/resign.js +0 -1
  14. package/build/commands/build/run.d.ts +1 -0
  15. package/build/commands/build/run.js +12 -3
  16. package/build/commands/integrations/convex/connect.d.ts +24 -0
  17. package/build/commands/integrations/convex/connect.js +266 -0
  18. package/build/commands/integrations/convex/dashboard.d.ts +9 -0
  19. package/build/commands/integrations/convex/dashboard.js +42 -0
  20. package/build/commands/integrations/convex/project/delete.d.ts +13 -0
  21. package/build/commands/integrations/convex/project/delete.js +65 -0
  22. package/build/commands/integrations/convex/project.d.ts +9 -0
  23. package/build/commands/integrations/convex/project.js +28 -0
  24. package/build/commands/integrations/convex/team/delete.d.ts +17 -0
  25. package/build/commands/integrations/convex/team/delete.js +93 -0
  26. package/build/commands/integrations/convex/team/invite.d.ts +19 -0
  27. package/build/commands/integrations/convex/team/invite.js +113 -0
  28. package/build/commands/integrations/convex/team.d.ts +9 -0
  29. package/build/commands/integrations/convex/team.js +35 -0
  30. package/build/commands/observe/events.js +12 -24
  31. package/build/commands/observe/logs.d.ts +29 -0
  32. package/build/commands/observe/logs.js +163 -0
  33. package/build/commands/observe/metrics.js +11 -19
  34. package/build/commands/observe/versions.js +11 -19
  35. package/build/commands/simulator/start.js +84 -5
  36. package/build/commands/simulator/stop.js +1 -1
  37. package/build/fingerprint/cli.js +1 -0
  38. package/build/graphql/generated.d.ts +421 -7
  39. package/build/graphql/generated.js +16 -3
  40. package/build/graphql/mutations/ConvexMutation.d.ts +10 -0
  41. package/build/graphql/mutations/ConvexMutation.js +89 -0
  42. package/build/graphql/mutations/DeviceRunSessionMutation.d.ts +2 -2
  43. package/build/graphql/mutations/DeviceRunSessionMutation.js +4 -4
  44. package/build/graphql/queries/ConvexQuery.d.ts +6 -0
  45. package/build/graphql/queries/ConvexQuery.js +49 -0
  46. package/build/graphql/queries/ObserveQuery.d.ts +21 -1
  47. package/build/graphql/queries/ObserveQuery.js +80 -0
  48. package/build/graphql/types/ConvexTeamConnection.d.ts +11 -0
  49. package/build/graphql/types/ConvexTeamConnection.js +43 -0
  50. package/build/graphql/types/Observe.d.ts +1 -0
  51. package/build/graphql/types/Observe.js +26 -1
  52. package/build/observe/fetchCustomEvents.d.ts +19 -0
  53. package/build/observe/fetchCustomEvents.js +21 -0
  54. package/build/observe/formatCustomEvents.d.ts +70 -0
  55. package/build/observe/formatCustomEvents.js +140 -0
  56. package/build/observe/formatEvents.js +5 -34
  57. package/build/observe/formatMetrics.js +2 -7
  58. package/build/observe/formatUtils.d.ts +27 -0
  59. package/build/observe/formatUtils.js +64 -0
  60. package/build/observe/formatVersions.js +2 -9
  61. package/build/observe/platforms.d.ts +21 -0
  62. package/build/observe/platforms.js +48 -0
  63. package/build/observe/resolveProjectContext.d.ts +22 -0
  64. package/build/observe/resolveProjectContext.js +21 -0
  65. package/build/run/ios/run.d.ts +2 -1
  66. package/build/run/ios/run.js +6 -2
  67. package/build/run/ios/simulator.d.ts +4 -1
  68. package/build/run/ios/simulator.js +14 -2
  69. package/build/run/run.d.ts +2 -1
  70. package/build/run/run.js +2 -2
  71. package/oclif.manifest.json +3984 -3243
  72. package/package.json +4 -4
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
5
+ const core_1 = require("@oclif/core");
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const dotenv_1 = tslib_1.__importDefault(require("dotenv"));
8
+ const fs = tslib_1.__importStar(require("fs-extra"));
9
+ const path_1 = tslib_1.__importDefault(require("path"));
10
+ const EasCommand_1 = tslib_1.__importDefault(require("../../../commandUtils/EasCommand"));
11
+ const convex_1 = require("../../../commandUtils/convex");
12
+ const flags_1 = require("../../../commandUtils/flags");
13
+ const ConvexMutation_1 = require("../../../graphql/mutations/ConvexMutation");
14
+ const ConvexQuery_1 = require("../../../graphql/queries/ConvexQuery");
15
+ const log_1 = tslib_1.__importDefault(require("../../../log"));
16
+ const ora_1 = require("../../../ora");
17
+ const projectUtils_1 = require("../../../project/projectUtils");
18
+ const prompts_1 = require("../../../prompts");
19
+ const CONVEX_REGIONS = [
20
+ { title: 'US East (aws-us-east-1)', value: 'aws-us-east-1' },
21
+ { title: 'EU West (aws-eu-west-1)', value: 'aws-eu-west-1' },
22
+ ];
23
+ const DEFAULT_REGION = 'aws-us-east-1';
24
+ class IntegrationsConvexConnect extends EasCommand_1.default {
25
+ static description = 'connect Convex to your Expo project';
26
+ static contextDefinition = {
27
+ ...this.ContextOptions.ProjectConfig,
28
+ };
29
+ static flags = {
30
+ ...flags_1.EASNonInteractiveFlag,
31
+ region: core_1.Flags.string({
32
+ description: 'Convex deployment region (e.g. aws-us-east-1, aws-eu-west-1)',
33
+ options: CONVEX_REGIONS.map(r => r.value),
34
+ }),
35
+ 'team-name': core_1.Flags.string({
36
+ description: 'Name for the new Convex team (defaults to EAS account name)',
37
+ }),
38
+ 'project-name': core_1.Flags.string({
39
+ description: 'Name for the Convex project (defaults to app slug)',
40
+ }),
41
+ };
42
+ async runAsync() {
43
+ const { flags: { region: regionFlag, 'team-name': teamNameFlag, 'project-name': projectNameFlag, 'non-interactive': nonInteractive, }, } = await this.parse(IntegrationsConvexConnect);
44
+ const { privateProjectConfig: { projectId, exp, projectDir }, loggedIn: { graphqlClient, actor }, } = await this.getContextAsync(IntegrationsConvexConnect, {
45
+ nonInteractive,
46
+ withServerSideEnvironment: null,
47
+ });
48
+ const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
49
+ // 1. Check for existing Convex team connections
50
+ const existingConnections = await ConvexQuery_1.ConvexQuery.getConvexTeamConnectionsByAccountIdAsync(graphqlClient, account.id);
51
+ const region = await this.resolveRegionAsync(regionFlag, nonInteractive);
52
+ let connection = null;
53
+ let teamName = null;
54
+ if (existingConnections.length === 0) {
55
+ // 2a. No connection - resolve a team name and create it after local package install succeeds
56
+ teamName = await this.resolveTeamNameAsync(teamNameFlag, account.name, nonInteractive);
57
+ }
58
+ else if (existingConnections.length === 1) {
59
+ // 2b. Single existing connection
60
+ connection = existingConnections[0];
61
+ log_1.default.withTick(`Using existing Convex team ${chalk_1.default.bold((0, convex_1.formatConvexTeam)(connection))}`);
62
+ }
63
+ else {
64
+ // 2c. Multiple connections - prompt to select
65
+ connection = await this.selectConnectionAsync(existingConnections, nonInteractive);
66
+ }
67
+ // 3. Resolve project name before project setup mutation
68
+ const projectName = await this.resolveProjectNameAsync(projectNameFlag, exp.slug, nonInteractive);
69
+ // 4. Install the Convex package before creating new server-side resources
70
+ await this.installConvexPackageAsync(projectDir);
71
+ if (!connection) {
72
+ const spinner = (0, ora_1.ora)('Creating Convex team').start();
73
+ try {
74
+ connection = await ConvexMutation_1.ConvexMutation.createConvexTeamConnectionAsync(graphqlClient, {
75
+ accountId: account.id,
76
+ deploymentRegion: region,
77
+ convexTeamName: teamName ?? account.name,
78
+ });
79
+ spinner.succeed(`Created Convex team ${chalk_1.default.bold((0, convex_1.formatConvexTeam)(connection))}`);
80
+ }
81
+ catch (error) {
82
+ spinner.fail('Failed to create Convex team');
83
+ throw error;
84
+ }
85
+ }
86
+ // 5. Set up Convex project
87
+ const spinner = (0, ora_1.ora)('Setting up Convex project').start();
88
+ let setupResult;
89
+ try {
90
+ setupResult = await ConvexMutation_1.ConvexMutation.setupConvexProjectAsync(graphqlClient, {
91
+ appId: projectId,
92
+ convexTeamConnectionId: connection.id,
93
+ deploymentRegion: region,
94
+ projectName,
95
+ });
96
+ spinner.succeed(`Created Convex project ${chalk_1.default.bold(projectName)} with deployment ${chalk_1.default.bold(setupResult.convexDeploymentName)}`);
97
+ }
98
+ catch (error) {
99
+ spinner.fail('Failed to set up Convex project');
100
+ throw error;
101
+ }
102
+ // 6. Send team invite (non-fatal)
103
+ const teamInviteResult = await this.sendTeamInviteAsync(graphqlClient, connection, actor, {
104
+ nonInteractive,
105
+ });
106
+ // 7. Write deploy key and URL to .env.local
107
+ await this.writeEnvLocalAsync(projectDir, setupResult.deployKey, setupResult.convexDeploymentUrl, nonInteractive);
108
+ // 8. Success message
109
+ log_1.default.addNewLineIfNone();
110
+ log_1.default.log(chalk_1.default.green('Convex is ready!'));
111
+ log_1.default.newLine();
112
+ log_1.default.log('Next steps:');
113
+ log_1.default.log(` 1. Start the Convex dev server: ${chalk_1.default.cyan('npx convex dev')}`);
114
+ log_1.default.newLine();
115
+ if (teamInviteResult === 'sent') {
116
+ log_1.default.log(`Check your email for an invitation to join your Convex team. Accept it for full dashboard access.`);
117
+ }
118
+ }
119
+ async resolveRegionAsync(flagValue, nonInteractive) {
120
+ if (flagValue) {
121
+ return flagValue;
122
+ }
123
+ if (nonInteractive) {
124
+ return DEFAULT_REGION;
125
+ }
126
+ return await (0, prompts_1.selectAsync)('Select a Convex deployment region', CONVEX_REGIONS);
127
+ }
128
+ async resolveTeamNameAsync(flagValue, accountName, nonInteractive) {
129
+ if (flagValue) {
130
+ return flagValue;
131
+ }
132
+ if (nonInteractive) {
133
+ return accountName;
134
+ }
135
+ const { teamName } = await (0, prompts_1.promptAsync)({
136
+ type: 'text',
137
+ name: 'teamName',
138
+ message: 'Convex team name',
139
+ initial: accountName,
140
+ validate: (value) => (value.trim() ? true : 'Team name cannot be empty'),
141
+ });
142
+ return teamName;
143
+ }
144
+ async resolveProjectNameAsync(flagValue, slug, nonInteractive) {
145
+ if (flagValue) {
146
+ return flagValue;
147
+ }
148
+ if (nonInteractive) {
149
+ return slug;
150
+ }
151
+ const { projectName } = await (0, prompts_1.promptAsync)({
152
+ type: 'text',
153
+ name: 'projectName',
154
+ message: 'Convex project name',
155
+ initial: slug,
156
+ validate: (value) => (value.trim() ? true : 'Project name cannot be empty'),
157
+ });
158
+ return projectName;
159
+ }
160
+ async selectConnectionAsync(connections, nonInteractive) {
161
+ if (nonInteractive) {
162
+ return connections[0];
163
+ }
164
+ const choices = connections.map(c => ({
165
+ title: `${(0, convex_1.formatConvexTeam)(c)} (created ${new Date(c.createdAt).toLocaleDateString()})`,
166
+ value: c,
167
+ }));
168
+ return await (0, prompts_1.selectAsync)('Select a Convex team connection', choices);
169
+ }
170
+ getActorEmail(actor) {
171
+ return actor.__typename === 'User' ? actor.email : null;
172
+ }
173
+ async sendTeamInviteAsync(graphqlClient, connection, actor, { nonInteractive }) {
174
+ if (connection.hasBeenClaimed) {
175
+ log_1.default.warn('Convex team has already been claimed. Skipping Convex team invitation.');
176
+ return 'skipped';
177
+ }
178
+ const email = this.getActorEmail(actor);
179
+ if (!email) {
180
+ log_1.default.warn(`Could not determine your verified email address, so no Convex team invitation was sent. Run ${chalk_1.default.cyan('eas integrations:convex:team:invite')} after signing in with a user account.`);
181
+ return 'skipped';
182
+ }
183
+ if (!(await (0, convex_1.confirmRecentConvexInviteAsync)(connection, { nonInteractive }))) {
184
+ log_1.default.warn('Skipped sending Convex team invitation.');
185
+ return 'skipped';
186
+ }
187
+ try {
188
+ await ConvexMutation_1.ConvexMutation.sendConvexTeamInviteToVerifiedEmailAsync(graphqlClient, {
189
+ convexTeamConnectionId: connection.id,
190
+ });
191
+ log_1.default.withTick(`Sent Convex team invitation to ${chalk_1.default.bold(email)}`);
192
+ return 'sent';
193
+ }
194
+ catch (error) {
195
+ log_1.default.warn(`Failed to send Convex team invitation to ${email}. Run ${chalk_1.default.cyan('eas integrations:convex:team:invite')} to retry.`);
196
+ log_1.default.warn(error instanceof Error ? error.message : String(error));
197
+ return 'failed';
198
+ }
199
+ }
200
+ async installConvexPackageAsync(projectDir) {
201
+ log_1.default.newLine();
202
+ log_1.default.log(`Running ${chalk_1.default.bold('npx expo install convex')}`);
203
+ log_1.default.newLine();
204
+ try {
205
+ await (0, spawn_async_1.default)('npx', ['expo', 'install', 'convex'], {
206
+ cwd: projectDir,
207
+ stdio: 'inherit',
208
+ });
209
+ log_1.default.withTick(`Installed the ${chalk_1.default.bold('convex')} npm package`);
210
+ }
211
+ catch (error) {
212
+ log_1.default.warn(`Failed to install the ${chalk_1.default.bold('convex')} npm package. Run ${chalk_1.default.cyan('npx expo install convex')} from your project directory, then run ${chalk_1.default.cyan('npx convex dev')}.`);
213
+ throw error;
214
+ }
215
+ }
216
+ async writeEnvLocalAsync(projectDir, deployKey, convexUrl, nonInteractive) {
217
+ const envPath = path_1.default.join(projectDir, '.env.local');
218
+ let existingContent = {};
219
+ let rawContent = '';
220
+ if (await fs.pathExists(envPath)) {
221
+ rawContent = await fs.readFile(envPath, 'utf8');
222
+ existingContent = dotenv_1.default.parse(rawContent);
223
+ if (existingContent.CONVEX_DEPLOY_KEY && !nonInteractive) {
224
+ const overwrite = await (0, prompts_1.confirmAsync)({
225
+ message: `.env.local already contains CONVEX_DEPLOY_KEY. Overwrite Convex values?`,
226
+ });
227
+ if (!overwrite) {
228
+ log_1.default.log('Skipping .env.local update. Deploy key:');
229
+ log_1.default.log(` CONVEX_DEPLOY_KEY=${deployKey}`);
230
+ log_1.default.log(` EXPO_PUBLIC_CONVEX_URL=${convexUrl}`);
231
+ return;
232
+ }
233
+ }
234
+ }
235
+ const updatedContent = this.mergeEnvContent(rawContent, {
236
+ CONVEX_DEPLOY_KEY: deployKey,
237
+ EXPO_PUBLIC_CONVEX_URL: convexUrl,
238
+ });
239
+ await fs.writeFile(envPath, updatedContent);
240
+ log_1.default.withTick(`Wrote Convex config to ${chalk_1.default.bold('.env.local')}`);
241
+ }
242
+ mergeEnvContent(rawContent, newVars) {
243
+ let content = rawContent;
244
+ const keysToAdd = { ...newVars };
245
+ for (const [key, value] of Object.entries(newVars)) {
246
+ // Replace existing line if present
247
+ const regex = new RegExp(`^${key}=.*$`, 'm');
248
+ if (regex.test(content)) {
249
+ content = content.replace(regex, `${key}=${value}`);
250
+ delete keysToAdd[key];
251
+ }
252
+ }
253
+ // Append any keys that weren't already in the file
254
+ const remaining = Object.entries(keysToAdd);
255
+ if (remaining.length > 0) {
256
+ if (content.length > 0 && !content.endsWith('\n')) {
257
+ content += '\n';
258
+ }
259
+ for (const [key, value] of remaining) {
260
+ content += `${key}=${value}\n`;
261
+ }
262
+ }
263
+ return content;
264
+ }
265
+ }
266
+ exports.default = IntegrationsConvexConnect;
@@ -0,0 +1,9 @@
1
+ import EasCommand from '../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexDashboard extends EasCommand {
3
+ static description: string;
4
+ static contextDefinition: {
5
+ loggedIn: import("../../../commandUtils/context/LoggedInContextField").default;
6
+ privateProjectConfig: import("../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
7
+ };
8
+ runAsync(): Promise<void>;
9
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const better_opn_1 = tslib_1.__importDefault(require("better-opn"));
5
+ const EasCommand_1 = tslib_1.__importDefault(require("../../../commandUtils/EasCommand"));
6
+ const convex_1 = require("../../../commandUtils/convex");
7
+ const ConvexQuery_1 = require("../../../graphql/queries/ConvexQuery");
8
+ const ora_1 = require("../../../ora");
9
+ class IntegrationsConvexDashboard extends EasCommand_1.default {
10
+ static description = 'open the Convex dashboard for the linked Convex project';
11
+ static contextDefinition = {
12
+ ...this.ContextOptions.ProjectConfig,
13
+ };
14
+ async runAsync() {
15
+ const { privateProjectConfig: { projectId, exp }, loggedIn: { graphqlClient }, } = await this.getContextAsync(IntegrationsConvexDashboard, {
16
+ nonInteractive: false,
17
+ withServerSideEnvironment: null,
18
+ });
19
+ const convexProject = await ConvexQuery_1.ConvexQuery.getConvexProjectByAppIdAsync(graphqlClient, projectId);
20
+ if (!convexProject) {
21
+ (0, convex_1.logNoConvexProject)(exp.slug);
22
+ return;
23
+ }
24
+ const dashboardUrl = (0, convex_1.getConvexProjectDashboardUrl)(convexProject);
25
+ const failedMessage = `Unable to open a web browser. Convex dashboard is available at: ${dashboardUrl}`;
26
+ const spinner = (0, ora_1.ora)(`Opening ${dashboardUrl}`).start();
27
+ try {
28
+ const opened = await (0, better_opn_1.default)(dashboardUrl);
29
+ if (opened) {
30
+ spinner.succeed(`Opened ${dashboardUrl}`);
31
+ }
32
+ else {
33
+ spinner.fail(failedMessage);
34
+ }
35
+ }
36
+ catch (error) {
37
+ spinner.fail(failedMessage);
38
+ throw error;
39
+ }
40
+ }
41
+ }
42
+ exports.default = IntegrationsConvexDashboard;
@@ -0,0 +1,13 @@
1
+ import EasCommand from '../../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexProjectDelete extends EasCommand {
3
+ static description: string;
4
+ static flags: {
5
+ yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
6
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ static contextDefinition: {
9
+ loggedIn: import("../../../../commandUtils/context/LoggedInContextField").default;
10
+ privateProjectConfig: import("../../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
11
+ };
12
+ runAsync(): Promise<void>;
13
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const EasCommand_1 = tslib_1.__importDefault(require("../../../../commandUtils/EasCommand"));
7
+ const convex_1 = require("../../../../commandUtils/convex");
8
+ const flags_1 = require("../../../../commandUtils/flags");
9
+ const ConvexMutation_1 = require("../../../../graphql/mutations/ConvexMutation");
10
+ const ConvexQuery_1 = require("../../../../graphql/queries/ConvexQuery");
11
+ const log_1 = tslib_1.__importStar(require("../../../../log"));
12
+ const ora_1 = require("../../../../ora");
13
+ const prompts_1 = require("../../../../prompts");
14
+ class IntegrationsConvexProjectDelete extends EasCommand_1.default {
15
+ static description = 'remove the Convex project link for the current Expo app from EAS servers';
16
+ static flags = {
17
+ ...flags_1.EASNonInteractiveFlag,
18
+ yes: core_1.Flags.boolean({
19
+ char: 'y',
20
+ description: 'Skip confirmation prompt',
21
+ default: false,
22
+ }),
23
+ };
24
+ static contextDefinition = {
25
+ ...this.ContextOptions.ProjectConfig,
26
+ };
27
+ async runAsync() {
28
+ const { flags: { 'non-interactive': nonInteractive, yes }, } = await this.parse(IntegrationsConvexProjectDelete);
29
+ const { privateProjectConfig: { projectId, exp }, loggedIn: { graphqlClient }, } = await this.getContextAsync(IntegrationsConvexProjectDelete, {
30
+ nonInteractive,
31
+ withServerSideEnvironment: null,
32
+ });
33
+ const convexProject = await ConvexQuery_1.ConvexQuery.getConvexProjectByAppIdAsync(graphqlClient, projectId);
34
+ if (!convexProject) {
35
+ (0, convex_1.logNoConvexProject)(exp.slug);
36
+ return;
37
+ }
38
+ log_1.default.addNewLineIfNone();
39
+ log_1.default.log((0, convex_1.formatConvexProject)(convexProject));
40
+ log_1.default.newLine();
41
+ const dashboardUrl = (0, convex_1.getConvexProjectDashboardUrl)(convexProject);
42
+ if (!nonInteractive && !yes) {
43
+ const confirmed = await (0, prompts_1.confirmAsync)({
44
+ message: `Remove this Convex project link from EAS servers? This does not destroy resources on Convex. Convex dashboard: ${(0, log_1.link)(dashboardUrl, { dim: false })}`,
45
+ });
46
+ if (!confirmed) {
47
+ log_1.default.error('Canceled deletion of the Convex project link');
48
+ return;
49
+ }
50
+ }
51
+ else {
52
+ log_1.default.warn(`Removing the Convex project link from EAS servers. This does not destroy resources on Convex: ${dashboardUrl}`);
53
+ }
54
+ const spinner = (0, ora_1.ora)('Removing Convex project link').start();
55
+ try {
56
+ await ConvexMutation_1.ConvexMutation.deleteConvexProjectAsync(graphqlClient, convexProject.id);
57
+ spinner.succeed(`Removed Convex project ${chalk_1.default.bold(convexProject.convexProjectName)} from EAS servers`);
58
+ }
59
+ catch (error) {
60
+ spinner.fail('Failed to remove Convex project link');
61
+ throw error;
62
+ }
63
+ }
64
+ }
65
+ exports.default = IntegrationsConvexProjectDelete;
@@ -0,0 +1,9 @@
1
+ import EasCommand from '../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexProject extends EasCommand {
3
+ static description: string;
4
+ static contextDefinition: {
5
+ loggedIn: import("../../../commandUtils/context/LoggedInContextField").default;
6
+ privateProjectConfig: import("../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
7
+ };
8
+ runAsync(): Promise<void>;
9
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
5
+ const EasCommand_1 = tslib_1.__importDefault(require("../../../commandUtils/EasCommand"));
6
+ const convex_1 = require("../../../commandUtils/convex");
7
+ const ConvexQuery_1 = require("../../../graphql/queries/ConvexQuery");
8
+ const log_1 = tslib_1.__importDefault(require("../../../log"));
9
+ class IntegrationsConvexProject extends EasCommand_1.default {
10
+ static description = 'display the Convex project linked to the current Expo app';
11
+ static contextDefinition = {
12
+ ...this.ContextOptions.ProjectConfig,
13
+ };
14
+ async runAsync() {
15
+ const { privateProjectConfig: { projectId, exp }, loggedIn: { graphqlClient }, } = await this.getContextAsync(IntegrationsConvexProject, {
16
+ nonInteractive: false,
17
+ withServerSideEnvironment: null,
18
+ });
19
+ const convexProject = await ConvexQuery_1.ConvexQuery.getConvexProjectByAppIdAsync(graphqlClient, projectId);
20
+ if (!convexProject) {
21
+ (0, convex_1.logNoConvexProject)(exp.slug);
22
+ return;
23
+ }
24
+ log_1.default.log(chalk_1.default.bold(`Convex project linked to ${exp.slug}`));
25
+ log_1.default.log((0, convex_1.formatConvexProject)(convexProject));
26
+ }
27
+ }
28
+ exports.default = IntegrationsConvexProject;
@@ -0,0 +1,17 @@
1
+ import EasCommand from '../../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexTeamDelete extends EasCommand {
3
+ static description: string;
4
+ static args: {
5
+ CONVEX_TEAM: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ static contextDefinition: {
12
+ loggedIn: import("../../../../commandUtils/context/LoggedInContextField").default;
13
+ privateProjectConfig: import("../../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
14
+ };
15
+ runAsync(): Promise<void>;
16
+ private resolveConnectionAsync;
17
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const EasCommand_1 = tslib_1.__importDefault(require("../../../../commandUtils/EasCommand"));
7
+ const convex_1 = require("../../../../commandUtils/convex");
8
+ const flags_1 = require("../../../../commandUtils/flags");
9
+ const ConvexMutation_1 = require("../../../../graphql/mutations/ConvexMutation");
10
+ const ConvexQuery_1 = require("../../../../graphql/queries/ConvexQuery");
11
+ const log_1 = tslib_1.__importStar(require("../../../../log"));
12
+ const ora_1 = require("../../../../ora");
13
+ const projectUtils_1 = require("../../../../project/projectUtils");
14
+ const prompts_1 = require("../../../../prompts");
15
+ class IntegrationsConvexTeamDelete extends EasCommand_1.default {
16
+ static description = "remove a Convex team link from the current Expo app owner account's EAS servers";
17
+ static args = {
18
+ CONVEX_TEAM: core_1.Args.string({
19
+ required: false,
20
+ description: 'Slug of the Convex team to remove',
21
+ }),
22
+ };
23
+ static flags = {
24
+ ...flags_1.EASNonInteractiveFlag,
25
+ yes: core_1.Flags.boolean({
26
+ char: 'y',
27
+ description: 'Skip confirmation prompt',
28
+ default: false,
29
+ }),
30
+ };
31
+ static contextDefinition = {
32
+ ...this.ContextOptions.ProjectConfig,
33
+ };
34
+ async runAsync() {
35
+ const { args: { CONVEX_TEAM: team }, flags: { 'non-interactive': nonInteractive, yes }, } = await this.parse(IntegrationsConvexTeamDelete);
36
+ const { privateProjectConfig: { projectId }, loggedIn: { graphqlClient }, } = await this.getContextAsync(IntegrationsConvexTeamDelete, {
37
+ nonInteractive,
38
+ withServerSideEnvironment: null,
39
+ });
40
+ const account = await (0, projectUtils_1.getOwnerAccountForProjectIdAsync)(graphqlClient, projectId);
41
+ const connections = await ConvexQuery_1.ConvexQuery.getConvexTeamConnectionsByAccountIdAsync(graphqlClient, account.id);
42
+ if (connections.length === 0) {
43
+ (0, convex_1.logNoConvexTeams)(account.name);
44
+ return;
45
+ }
46
+ const connection = await this.resolveConnectionAsync(connections, team, nonInteractive);
47
+ log_1.default.addNewLineIfNone();
48
+ log_1.default.log((0, convex_1.formatConvexTeamConnection)(connection));
49
+ log_1.default.newLine();
50
+ const dashboardUrl = (0, convex_1.getConvexTeamDashboardUrl)(connection);
51
+ if (!nonInteractive && !yes) {
52
+ const confirmed = await (0, prompts_1.confirmAsync)({
53
+ message: `Remove this Convex team link from EAS servers? This does not destroy resources on Convex. Convex dashboard: ${(0, log_1.link)(dashboardUrl, { dim: false })}`,
54
+ });
55
+ if (!confirmed) {
56
+ log_1.default.error('Canceled deletion of the Convex team link');
57
+ return;
58
+ }
59
+ }
60
+ else {
61
+ log_1.default.warn(`Removing the Convex team link from EAS servers. This does not destroy resources on Convex: ${dashboardUrl}`);
62
+ }
63
+ const spinner = (0, ora_1.ora)('Removing Convex team link').start();
64
+ try {
65
+ await ConvexMutation_1.ConvexMutation.deleteConvexTeamConnectionAsync(graphqlClient, connection.id);
66
+ spinner.succeed(`Removed Convex team ${chalk_1.default.bold((0, convex_1.formatConvexTeam)(connection))} from EAS servers`);
67
+ }
68
+ catch (error) {
69
+ spinner.fail('Failed to remove Convex team link');
70
+ throw error;
71
+ }
72
+ }
73
+ async resolveConnectionAsync(connections, team, nonInteractive) {
74
+ if (team) {
75
+ const connection = connections.find(item => item.convexTeamSlug === team || item.convexTeamName === team || item.id === team);
76
+ if (!connection) {
77
+ throw new Error(`Convex team ${team} is not linked to this account.`);
78
+ }
79
+ return connection;
80
+ }
81
+ if (connections.length === 1) {
82
+ return connections[0];
83
+ }
84
+ if (nonInteractive) {
85
+ throw new Error('Convex team slug must be provided in non-interactive mode when multiple Convex team links exist.');
86
+ }
87
+ return await (0, prompts_1.selectAsync)('Select a Convex team link to remove', connections.map(connection => ({
88
+ title: (0, convex_1.formatConvexTeam)(connection),
89
+ value: connection,
90
+ })));
91
+ }
92
+ }
93
+ exports.default = IntegrationsConvexTeamDelete;
@@ -0,0 +1,19 @@
1
+ import EasCommand from '../../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexTeamInvite extends EasCommand {
3
+ static description: string;
4
+ static args: {
5
+ CONVEX_TEAM: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ static contextDefinition: {
11
+ loggedIn: import("../../../../commandUtils/context/LoggedInContextField").default;
12
+ privateProjectConfig: import("../../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
13
+ };
14
+ runAsync(): Promise<void>;
15
+ private getActorEmail;
16
+ private logTeam;
17
+ private logPreviousInvite;
18
+ private resolveConnectionAsync;
19
+ }