Compare commits

..
21 Commits
Author SHA1 Message Date
Cedric van Putten 87b0cf41a8 v12.4.0 2024-09-14 13:07:15 +01:00
Cedric van Putten 7847b5297c refactor(eas-cli): always default to static uploads and add modified time (#2565)
* refactor(eas-cli): always default to static uploads and add modified time

* docs(eas-cli): add changelog entry

* chore(eas-cli): resolve linting issue

* fix(eas-cli): error when there are no deployments

* fix(eas-cli): remove unused `exp` var

* fix(eas-cli): fix json output again
2024-09-14 13:05:49 +01:00
Cedric van Putten 539ef8f3ad refactor(eas-cli): polish the dev domain prompt (#2564)
* refactor(eas-cli): polish the dev domain prompt

* docs(eas-cli): add changelog entry

* refactor(eas-cli): simplify the "already taken" message

* feature(eas-cli): add suggested project url to avoid conflicts
2024-09-14 12:44:55 +01:00
Cedric van Putten 819259ab1a feature(eas-cli): add worker:alias|promote --prod flag to promote existing deployments (#2563)
* feature(eas-cli): add `worker:alias --prod` flag to promote existing deployments

This also includes some clean ups and log utility sharing

* feature(eas-cli): support `worker:promote --prod --id`

* refactor(eas-cli): rename `/serverless/deployments` -> `/hosting/deployments`

* docs(eas-cli): add changelog entry

* chore(eas-cli): resolve linting issues

* fix(eas-cli): disable ora when possibly asking for a dev domain

* chore(eas-cli): resolve typing issue
2024-09-14 09:20:06 +01:00
Cedric van Putten 47e1989c9c feature(eas-cli): add worker:alias --json support for 3rd parties and custom tooling (#2562)
* feature(eas-cli): add `worker:alias --json` flag to integrate with 3rd parties

* docs(eas-cli): add changelog entry

* docs(eas-cli): fix changelog entry

* fix(eas-cli): lowercase deployment identifier

* fix(eas-cli): resolve linting issues
2024-09-13 16:14:21 +01:00
Cedric van Putten fa3262951b feature(eas-cli): add worker --json support for 3rd parties and custom tooling (#2561)
* feature(eas-cli): add `worker --json` flag to integrate with 3rd parties

* docs(eas-cli): add changelog entry

* refactor(eas-cli): rename `expoDashboardUrl` -> `dashboardUrl`

* chore(eas-cli): resolve linting issues

* docs(eas-cli): fix changelog entry
2024-09-13 16:09:04 +01:00
Cedric van Putten 66ce64e0a3 feature(eas-cli): add worker --export-dir to select exported directory (#2560)
* feature(eas-cli): add `worker --export-dir` flag to select export folder

* docs(eas-cli): add changelog entry

* fix(eas-cli): use `path.join` instead of `path.resolve`

`path.resolve` throws when the path does not exist, `path.join` uses our own validation errors.

* docs(eas-cli): fix changelog entry
2024-09-13 15:48:41 +01:00
Phil Pluckthun 5c553cee7b [eas-cli] Add --environment argument to worker:deploy (#2557)
* Add `--environment` argument to worker:deploy

* Add to changelog

* Apply lints
2024-09-13 13:15:30 +01:00
Cedric van Putten 2fb079d4bb refactor(eas-cli): update eas worker:alias with same polishes from eas worker (#2558)
* refactor(eas-cli): reuse same working in `eas worker:alis` from `eas worker`

* refactor(eas-cli): reuse same result table from `eas worker`

* docs(eas-cli): update changelog entry

* refactor(eas-cli): use `Alias URL` instead of `Aliased URL`
2024-09-13 13:06:47 +01:00
Cedric van Putten d15cd90c81 refactor(eas-cli): support eas worker --production and clean up command output (#2555)
* refactor(eas-cli): add support for both `--prod` and `--production` flags in `eas worker`

* chore: add changelog entry

* refactor(eas-cli): also tweak `--help` output

* refactor(eas-cli): move `--prod` before `--alias`/`--id` in usage

* refactor(eas-cli): clean up ora spinners and add table output

* refactor(eas-cli): simplify project type detection

* refactor(eas-cli): simplify alias and production spinners

* docs(eas-cli): update changelog entry

* chore: resolve linting issues

* refactor(eas-cli): use `Alias URL` instead of `Aliased URL`

* fix(eas-cli): mark `production` as bold in ora spinners
2024-09-13 12:53:11 +01:00
Cedric van Putten 0fbd3e47f8 fix(eas-cli): avoid adding expo.extra data from config plugins in eas init (#2554)
* fix(eas-cli): avoid adding `expo.extra` data from config plugins in `eas init`

Note that in the newer `@expo/config` package, modifying now also merges existing properties. Once thats released, we can use that instead of manually merging this data.

* docs(eas-cli): add changelog entry
2024-09-12 15:10:40 +02:00
Cedric van Putten 12efaf12cc feature(eas-cli): add worker --id flag (#2552)
* feature(eas-cli): add `worker --id` flag

* docs: add changelog entry
2024-09-12 13:02:47 +02:00
Cedric van PuttenandSzymon Dziedzic a404bb383d feature(eas-cli): add worker --alias flag (#2551)
* feature(eas-cli): add `worker --alias` flag

* docs: add changelog entry

* fix(eas-cli): add missing `ora.start`

Co-authored-by: Szymon Dziedzic <[email protected]>

---------

Co-authored-by: Szymon Dziedzic <[email protected]>
2024-09-12 12:43:01 +02:00
Cedric van PuttenandSzymon Dziedzic feaa8cbf22 feature(eas-cli): add worker --prod flag and hint for production deployments (#2550)
* feature(eas-cli): add `worker --prod` flag and hint for production deployments

* docs: add changelog entry

* refactor(eas-cli): add Syzmons PR feedback

Co-authored-by: Szymon Dziedzic <[email protected]>

---------

Co-authored-by: Szymon Dziedzic <[email protected]>
2024-09-12 12:37:00 +02:00
Cedric van Putten 542ea7a791 feature(eas-cli): add worker:alias command (#2548)
* feature(eas-cli): add `worker:alias` command to assign aliases

* feature(eas-cli): add worker selection when assigning alias

* refactor(eas-cli): clean up comments and prompt for alias

* refactor(eas-cli): clean up command and flag descriptions

* chore: resolve linting issues

* docs: add changelog entry
2024-09-12 12:25:29 +02:00
dependabot[bot] 7d80b0540f Bump express from 4.19.2 to 4.20.0 (#2546)
Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.20.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-12 09:14:25 +02:00
dependabot[bot] cc4e0ebda1 Bump dset from 3.1.2 to 3.1.4 (#2553)
Bumps [dset](https://github.com/lukeed/dset) from 3.1.2 to 3.1.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/lukeed/dset/releases">dset's releases</a>.</em></p>
<blockquote>
<h2>v3.1.3</h2>
<h2>Patches</h2>
<ul>
<li>Add <code>&quot;types&quot;</code> export conditions for TypeScript <code>&quot;nodenext&quot;</code>/<code>&quot;node16&quot;</code> resolution: <a href="https://redirect.github.com/lukeed/dset/issues/40">#40</a>
<em>Thank you <a href="https://github.com/Akkuma"><code>@​Akkuma</code></a></em></li>
</ul>
<hr />
<p><strong>Full Changelog</strong>: <a href="https://github.com/lukeed/dset/compare/v3.1.2...v3.1.3">https://github.com/lukeed/dset/compare/v3.1.2...v3.1.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/lukeed/dset/commit/05b1ec0f8cebe3b5d5667285bc7da90f38a7215e"><code>05b1ec0</code></a> 3.1.4</li>
<li><a href="https://github.com/lukeed/dset/commit/16d6154e085bef01e99f01330e5a421a7f098afa"><code>16d6154</code></a> fix: prevent <strong>proto</strong> assignment via implicit string</li>
<li><a href="https://github.com/lukeed/dset/commit/48f14a1a4b2985c30663133e4699ddab69a393ac"><code>48f14a1</code></a> 3.1.3</li>
<li><a href="https://github.com/lukeed/dset/commit/aca90fb54b908de0042b7da0d45ef3ca0ea9671a"><code>aca90fb</code></a> chore: add &quot;types&quot; conditions for TS &quot;nodenext&quot; resolution (<a href="https://redirect.github.com/lukeed/dset/issues/40">#40</a>)</li>
<li>See full diff in <a href="https://github.com/lukeed/dset/compare/v3.1.2...v3.1.4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dset&package-manager=npm_and_yarn&previous-version=3.1.2&new-version=3.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/expo/eas-cli/network/alerts).

</details>
2024-09-12 09:13:49 +02:00
Phil Pluckthun 1621fb3a9b feat(cli): Source @expo/env dotenv vars for worker deployments (#2545)
* Add `@expo/env`

* Source env variables from ".env" via `@expo/env` to deployment

* Add CHANGELOG

* Increase requested range for `@expo/env`

* Apply lints
2024-09-11 13:03:08 +01:00
Phil Pluckthun 51b5946854 chore(cli): Add --non-interactive flag to fix worker:deploy initialisation (#2544) 2024-09-10 18:00:03 +01:00
Szymon Dziedzic b8ed63cadc [eas-cli] improve error message when CFBundleShortVersionString has invalid format (#2542)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. -->
<!-- You can skip the changelog check by labeling the PR with "no changelog". -->

# Why

https://exponent-internal.slack.com/archives/C017N0N99RA/p1725915931423649

# How

Improve error message to make it more actionable

# Test Plan

Test manually

![Screenshot 2024-09-10 at 12.39.27.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/9YRXgAETSTRMfjZ0IP35/0c5ad653-3e55-43e0-bc12-aa4b30f730eb.png)

![Screenshot 2024-09-10 at 12.34.51.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/9YRXgAETSTRMfjZ0IP35/2e8f9e21-1d06-4c6c-8cc0-f263c9455bae.png)
2024-09-10 16:01:42 +02:00
Expo CI 8fc0648419 update CHANGELOG.md 2024-09-09 15:41:29 +00:00
21 changed files with 4146 additions and 1513 deletions

No files matched your search

+25 -1
View File
@@ -8,12 +8,36 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Add `--non-interactive` and `--force` support when `--id` is not passed to the `eas init` command. ([#1983](https://github.com/expo/eas-cli/pull/1983) by [@mymattcarroll](https://github.com/mymattcarroll))
- Add `worker:alias` command to assign aliases from the CLI. ([#2548](https://github.com/expo/eas-cli/pull/2548) by [@byCedric](https://github.com/byCedric))
- Add `worker --prod` flag to deploy to production from the CLI. ([#2550](https://github.com/expo/eas-cli/pull/2550) by [@byCedric](https://github.com/byCedric))
- Add `worker --alias` flag to assign custom aliases when deploying. ([#2551](https://github.com/expo/eas-cli/pull/2551) by [@byCedric](https://github.com/byCedric)))
- Add `worker --id` flag to use a custom deployment identifier. ([#2552](https://github.com/expo/eas-cli/pull/2552) by [@byCedric](https://github.com/byCedric)))
- Add `worker --environment` flag to deploy with EAS environment variables. ([#2557](https://github.com/expo/eas-cli/pull/2557) by [@kitten](https://github.com/kitten)))
- Add `worker --export-dir` flag to select exported directory. ([#2560](https://github.com/expo/eas-cli/pull/2560) by [@byCedric](https://github.com/byCedric)))
- Add `worker --json` flag to allow integrating with 3rd parties and custom tooling. ([#2561](https://github.com/expo/eas-cli/pull/2561) by [@byCedric](https://github.com/byCedric)))
- Add `worker:alias --json` flag to allow integrating with 3rd parties and custom tooling. ([#2562](https://github.com/expo/eas-cli/pull/2562) by [@byCedric](https://github.com/byCedric)))
### 🐛 Bug fixes
- Avoid merging `expo.extra` plugin-generated data with `expo.extra.eas.projectId` in `eas init`. ([#2554](https://github.com/expo/eas-cli/pull/2554) by [@byCedric](https://github.com/byCedric)))
### 🧹 Chores
- Make error message for invalid CFBundleShortVersionString more descriptive and actionable. Improve CFBundleShortVersionString validation regex. ([#2542](https://github.com/expo/eas-cli/pull/2542) by [@szdziedzic](https://github.com/szdziedzic))
- Add missing `--non-interactive` argument to `worker:deploy` command. ([#2544](https://github.com/expo/eas-cli/pull/2544) by [@kitten](https://github.com/kitten))
- Source `@expo/env` dotenv files for worker deployments. ([#2545](https://github.com/expo/eas-cli/pull/2545) by [@kitten](https://github.com/kitten))
- Support `worker --production` and clean up command output. ([#2555](https://github.com/expo/eas-cli/pull/2555) by [@byCedric](https://github.com/byCedric)))
- Unify both `worker` and `worker:alias` command output. ([#2558](https://github.com/expo/eas-cli/pull/2558) by [@byCedric](https://github.com/byCedric)))
- Share similar table/json output in both `worker` and `worker:alias` command outputs. ([#2563](https://github.com/expo/eas-cli/pull/2563) by [@byCedric](https://github.com/byCedric)))
- Polish the project URL prompt when setting up new projects. ([#2564](https://github.com/expo/eas-cli/pull/2564) by [@byCedric](https://github.com/byCedric)))
- Always assume `static` exports in `eas deploy` and add modified time. ([#2565](https://github.com/expo/eas-cli/pull/2565) by [@byCedric](https://github.com/byCedric)))
## [12.3.0](https://github.com/expo/eas-cli/releases/tag/v12.3.0) - 2024-09-09
### 🎉 New features
- Add `--non-interactive` and `--force` support when `--id` is not passed to the `eas init` command. ([#1983](https://github.com/expo/eas-cli/pull/1983) by [@mymattcarroll](https://github.com/mymattcarroll))
## [12.1.1](https://github.com/expo/eas-cli/releases/tag/v12.1.1) - 2024-09-09
### 🐛 Bug fixes
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "12.3.0",
"version": "12.4.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+60 -60
View File
@@ -143,7 +143,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/account/login.ts)_
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -160,7 +160,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -177,7 +177,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/account/view.ts)_
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -191,7 +191,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -243,7 +243,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -264,7 +264,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -284,7 +284,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -304,7 +304,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -327,7 +327,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -364,7 +364,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/index.ts)_
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -383,7 +383,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -400,7 +400,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -419,7 +419,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/delete.ts)_
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:inspect`
@@ -454,7 +454,7 @@ DESCRIPTION
inspect the state of the project at specific build stages, useful for troubleshooting
```
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -504,7 +504,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/list.ts)_
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -533,7 +533,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/resign.ts)_
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -559,7 +559,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/run.ts)_
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -609,7 +609,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/version/get.ts)_
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -628,7 +628,7 @@ DESCRIPTION
update version of an app
```
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/version/set.ts)_
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -647,7 +647,7 @@ DESCRIPTION
update a version in native code with a value stored on EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/version/sync.ts)_
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -664,7 +664,7 @@ DESCRIPTION
view a build for your project
```
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/build/view.ts)_
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -685,7 +685,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -707,7 +707,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -727,7 +727,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -760,7 +760,7 @@ DESCRIPTION
Roll a new branch out on a channel incrementally.
```
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/channel/rollout.ts)_
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -783,7 +783,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -804,7 +804,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -821,7 +821,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/credentials/index.ts)_
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -839,7 +839,7 @@ DESCRIPTION
Set up credentials for building your project.
```
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas device:create`
@@ -853,7 +853,7 @@ DESCRIPTION
register new Apple Devices to use for internal distribution
```
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/device/create.ts)_
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -873,7 +873,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -894,7 +894,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/device/list.ts)_
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -915,7 +915,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/device/rename.ts)_
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -929,7 +929,7 @@ DESCRIPTION
view a device for your project
```
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/device/view.ts)_
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -943,7 +943,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -1051,7 +1051,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1068,7 +1068,7 @@ DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1085,7 +1085,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1115,7 +1115,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1129,7 +1129,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/project/info.ts)_
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1152,7 +1152,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/project/init.ts)_
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
@@ -1170,7 +1170,7 @@ ALIASES
$ eas onboarding
```
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/project/onboarding.ts)_
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/project/onboarding.ts)_
## `eas secret:create`
@@ -1193,7 +1193,7 @@ DESCRIPTION
create an environment secret on the current project or owner account
```
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1211,7 +1211,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1225,7 +1225,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1245,7 +1245,7 @@ DESCRIPTION
read environment secrets from env file and store on the server
```
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1276,7 +1276,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1310,7 +1310,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/index.ts)_
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1328,7 +1328,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1349,7 +1349,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1371,7 +1371,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/list.ts)_
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1399,7 +1399,7 @@ DESCRIPTION
roll back to an existing update
```
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/republish.ts)_
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1427,7 +1427,7 @@ DESCRIPTION
roll back to the embedded update
```
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1447,7 +1447,7 @@ DESCRIPTION
roll back to an embedded update or an existing update
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/rollback.ts)_
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1467,7 +1467,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/update/view.ts)_
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1488,7 +1488,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1508,7 +1508,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1526,7 +1526,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1548,7 +1548,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1565,7 +1565,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v12.3.0/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v12.4.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
+2655 -1140
View File
File diff suppressed because it is too large. Load diff
+3 -2
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "12.3.0",
"version": "12.4.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -15,6 +15,7 @@
"@expo/config-types": "50.0.0",
"@expo/eas-build-job": "1.0.133",
"@expo/eas-json": "12.0.0",
"@expo/env": "^0.3.0",
"@expo/json-file": "8.2.37",
"@expo/logger": "1.0.117",
"@expo/multipart-body-parser": "1.1.0",
@@ -113,7 +114,7 @@
"@types/wrap-ansi": "3.0.0",
"axios": "0.28.1",
"eslint-plugin-graphql": "4.0.0",
"express": "4.19.2",
"express": "4.20.0",
"memfs": "3.4.13",
"mockdate": "3.0.5",
"nock": "13.4.0",
@@ -5,6 +5,7 @@ import { vol } from 'memfs';
import os from 'os';
import type { XCBuildConfiguration } from 'xcode';
import { learnMore } from '../../../log';
import { readPlistAsync } from '../../../utils/plist';
import { resolveVcsClient } from '../../../vcs';
import {
@@ -316,7 +317,9 @@ describe(readShortVersionAsync, () => {
vcsClient
)
).rejects.toThrowError(
'CFBundleShortVersionString (version field in app.json/app.config.js) must be a period-separated list of three non-negative integers. Current value: 0.0.7.1.028'
`The required format for "CFBundleShortVersionString" in Info.plist is one to three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods. Current value: 0.0.7.1.028. Edit the "CFBundleShortVersionString" in your Info.plist to match the required format. ${learnMore(
'https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring'
)}`
);
});
});
+24 -8
View File
@@ -11,7 +11,7 @@ import { Target } from '../../credentials/ios/types';
import { AppPlatform } from '../../graphql/generated';
import { AppVersionMutation } from '../../graphql/mutations/AppVersionMutation';
import { AppVersionQuery } from '../../graphql/queries/AppVersionQuery';
import Log from '../../log';
import Log, { learnMore } from '../../log';
import { ora } from '../../ora';
import { findApplicationTarget } from '../../project/ios/target';
import { getNextBuildNumber, isValidBuildNumber } from '../../project/ios/versions';
@@ -23,7 +23,7 @@ import { Client } from '../../vcs/vcs';
import { updateAppJsonConfigAsync } from '../utils/appJson';
import { bumpAppVersionAsync, ensureStaticConfigExists } from '../utils/version';
const SHORT_VERSION_REGEX = /^\d+.\d+.\d+$/;
const SHORT_VERSION_REGEX = /^\d+(\.\d+){0,2}$/;
export enum BumpStrategy {
APP_VERSION,
@@ -100,11 +100,27 @@ export async function bumpVersionInAppJsonAsync({
}
}
function validateShortVersion(shortVersion: string | undefined): void {
function validateShortVersion({
shortVersion,
workflow,
}: {
shortVersion: string | undefined;
workflow: Workflow;
}): void {
if (shortVersion && !SHORT_VERSION_REGEX.test(shortVersion)) {
throw new Error(
`CFBundleShortVersionString (version field in app.json/app.config.js) must be a period-separated list of three non-negative integers. Current value: ${shortVersion}`
);
if (workflow === Workflow.MANAGED) {
throw new Error(
`The required format for "version" field from app.json/app.config.ts is one to three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods. Current value: ${shortVersion}. Edit the "version" field in your app.json/app.config.ts to match the required format. ${learnMore(
'https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring'
)}`
);
} else {
throw new Error(
`The required format for "CFBundleShortVersionString" in Info.plist is one to three period-separated integers, such as 10.14.1. The string can only contain numeric characters (0-9) and periods. Current value: ${shortVersion}. Edit the "CFBundleShortVersionString" in your Info.plist to match the required format. ${learnMore(
'https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring'
)}`
);
}
}
}
@@ -122,10 +138,10 @@ export async function readShortVersionAsync(
infoPlist.CFBundleShortVersionString &&
evaluateTemplateString(infoPlist.CFBundleShortVersionString, buildSettings);
validateShortVersion(shortVersion);
validateShortVersion({ shortVersion, workflow });
return shortVersion;
} else {
validateShortVersion(exp.version);
validateShortVersion({ shortVersion: exp.version, workflow });
return exp.version;
}
}
@@ -18,13 +18,15 @@ import { Actor, getActorUsername } from '../../../user/User';
* Save an EAS project ID to the appropriate field in the app config.
*
* @deprecated Should not be used outside of context functions except in the init command.
* @deprecated Starting from `@expo/config` from SDK 52, the `modifyConfigAsync` function is merging existing data. Once this is released, we can use that instead of manually merging.
*/
export async function saveProjectIdToAppConfigAsync(
projectDir: string,
projectId: string,
options: { env?: Env } = {}
): Promise<void> {
const exp = getPrivateExpoConfig(projectDir, options);
// NOTE(cedric): we disable plugins to avoid writing plugin-generated content to `expo.extra`
const exp = getPrivateExpoConfig(projectDir, { skipPlugins: true, ...options });
const result = await createOrModifyExpoConfigAsync(
projectDir,
{
@@ -0,0 +1,237 @@
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import EasCommand from '../../commandUtils/EasCommand';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import { WorkerDeploymentAliasFragment } from '../../graphql/generated';
import Log from '../../log';
import { Ora, ora } from '../../ora';
import { promptAsync } from '../../prompts';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import {
assignWorkerDeploymentAliasAsync,
assignWorkerDeploymentProductionAsync,
selectWorkerDeploymentOnAppAsync,
} from '../../worker/deployment';
import { formatWorkerDeploymentJson, formatWorkerDeploymentTable } from '../../worker/utils/logs';
interface DeployAliasFlags {
nonInteractive: boolean;
json: boolean;
aliasName?: string | null;
deploymentIdentifier?: string | null;
isProduction: boolean;
}
interface RawDeployAliasFlags {
'non-interactive': boolean;
json: boolean;
alias?: string;
id?: string;
prod: boolean;
}
export default class WorkerAlias extends EasCommand {
static override description = 'Assign deployment aliases';
static override aliases = ['deploy:alias', 'deploy:promote'];
// TODO(@kitten): Keep command hidden until worker deployments are live
static override hidden = true;
static override state = 'beta';
static override flags = {
prod: Flags.boolean({
aliases: ['production'],
description: 'Promote an existing deployment to production',
default: false,
}),
alias: Flags.string({
description: 'Custom alias to assign to the existing deployment',
helpValue: 'name',
required: false,
}),
id: Flags.string({
description: 'Unique identifier of an existing deployment',
helpValue: 'xyz123',
required: false,
}),
...EasNonInteractiveAndJsonFlags,
};
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.LoggedIn,
};
override async runAsync(): Promise<void> {
// NOTE(cedric): `Log.warn` uses `console.log`, which is incorrect when running with `--json`
// eslint-disable-next-line no-console
console.warn(
chalk.yellow('EAS Worker Deployments are in beta and subject to breaking changes.')
);
const { flags: rawFlags } = await this.parse(WorkerAlias);
const flags = this.sanitizeFlags(rawFlags);
if (flags.json) {
enableJsonOutput();
}
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
} = await this.getContextAsync(WorkerAlias, {
nonInteractive: true,
});
const { projectId } = await getDynamicPrivateProjectConfigAsync();
const aliasName = await resolveDeploymentAliasAsync(flags);
const deploymentId = await resolveDeploymentIdAsync({
...flags,
graphqlClient,
projectId,
aliasName,
});
let progress: null | Ora = null;
let deploymentAlias: null | Awaited<ReturnType<typeof assignWorkerDeploymentAliasAsync>> = null;
if (aliasName) {
try {
progress = ora(chalk`Assigning alias {bold ${aliasName}} to deployment`).start();
deploymentAlias = await assignWorkerDeploymentAliasAsync({
graphqlClient,
appId: projectId,
deploymentId,
aliasName,
});
progress.text = chalk`Assigned alias {bold ${aliasName}} to deployment`;
} catch (error: any) {
progress?.fail(chalk`Failed to assign {bold ${aliasName}} alias to deployment`);
throw error;
}
}
let deploymentProdAlias: null | Awaited<
ReturnType<typeof assignWorkerDeploymentProductionAsync>
> = null;
if (flags.isProduction) {
try {
progress = (progress ?? ora()).start(chalk`Promoting deployment to {bold production}`);
deploymentProdAlias = await assignWorkerDeploymentProductionAsync({
graphqlClient,
appId: projectId,
deploymentId,
});
progress.text = chalk`Promoted deployment to {bold production}`;
} catch (error: any) {
progress?.fail(chalk`Failed to promote deployment to {bold production}`);
throw error;
}
}
progress?.succeed(
!deploymentAlias
? chalk`Promoted deployment to {bold production}`
: chalk`Promoted deployment to {bold production} with alias {bold ${deploymentAlias.aliasName}}`
);
// Either use the alias, or production deployment information
const deployment = deploymentAlias?.workerDeployment ?? deploymentProdAlias?.workerDeployment;
if (flags.json) {
printJsonOnlyOutput(
formatWorkerDeploymentJson({
projectId,
deployment: deployment!,
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
production: deploymentProdAlias,
})
);
return;
}
Log.addNewLineIfNone();
Log.log(`🎉 Your deployment is modified`);
Log.addNewLineIfNone();
Log.log(
formatWorkerDeploymentTable({
projectId,
deployment: deployment!,
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
production: deploymentProdAlias,
})
);
}
private sanitizeFlags(flags: RawDeployAliasFlags): DeployAliasFlags {
return {
nonInteractive: flags['non-interactive'],
json: flags['json'],
aliasName: flags.alias?.trim().toLowerCase(),
deploymentIdentifier: flags.id?.trim().toLowerCase(),
isProduction: flags.prod,
};
}
}
async function resolveDeploymentAliasAsync(flags: DeployAliasFlags): Promise<string | null> {
if (flags.aliasName?.trim()) {
return flags.aliasName.trim().toLowerCase();
}
// Skip alias prompt when promoting deployments to prod
if (flags.isProduction) {
return null;
}
if (flags.nonInteractive) {
throw new Error('The `--alias` flag must be set when running in `--non-interactive` mode.');
}
const { alias: aliasName } = await promptAsync({
type: 'text',
name: 'alias',
message: 'Enter the alias to assign to a deployment',
validate: (value: string) => !!value.trim(),
hint: 'The alias name is case insensitive and must be URL safe',
});
return aliasName.trim().toLowerCase();
}
async function resolveDeploymentIdAsync({
graphqlClient,
deploymentIdentifier,
aliasName,
projectId,
nonInteractive,
}: DeployAliasFlags & {
graphqlClient: ExpoGraphqlClient;
projectId: string;
}): Promise<string> {
if (deploymentIdentifier) {
return deploymentIdentifier;
}
if (nonInteractive) {
throw new Error('The `--id` flag must be set when running in `--non-interactive` mode.');
}
const deployment = await selectWorkerDeploymentOnAppAsync({
graphqlClient,
appId: projectId,
selectTitle: chalk`deployment to assign the {underline ${aliasName}} alias`,
});
if (!deployment) {
throw new Error(
'No deployments found for this project, create a new deployment with "eas deploy"'
);
}
return deployment.deploymentIdentifier;
}
+252 -76
View File
@@ -1,14 +1,31 @@
import { format as formatTimeAgo } from '@expo/timeago.js';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import fs from 'node:fs';
import * as path from 'node:path';
import EasCommand from '../../commandUtils/EasCommand';
import { EASEnvironmentFlag, EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
import {
EnvironmentVariableEnvironment,
WorkerDeploymentAliasFragment,
} from '../../graphql/generated';
import Log from '../../log';
import { ora } from '../../ora';
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
import { createProgressTracker } from '../../utils/progress';
import * as WorkerAssets from '../../worker/assets';
import { getSignedDeploymentUrlAsync } from '../../worker/deployment';
import {
assignWorkerDeploymentAliasAsync,
assignWorkerDeploymentProductionAsync,
getSignedDeploymentUrlAsync,
} from '../../worker/deployment';
import { UploadParams, batchUploadAsync, uploadAsync } from '../../worker/upload';
import {
formatWorkerDeploymentJson,
formatWorkerDeploymentTable,
getDeploymentUrlFromFullName,
} from '../../worker/utils/logs';
const isDirectory = (directoryPath: string): Promise<boolean> =>
fs.promises
@@ -16,16 +33,57 @@ const isDirectory = (directoryPath: string): Promise<boolean> =>
.then(stat => stat.isDirectory())
.catch(() => false);
interface DeployFlags {
nonInteractive: boolean;
json: boolean;
isProduction: boolean;
aliasName?: string;
environment?: EnvironmentVariableEnvironment;
deploymentIdentifier?: string;
exportDir: string;
}
interface RawDeployFlags {
'non-interactive': boolean;
environment?: string;
json: boolean;
prod: boolean;
alias?: string;
id?: string;
'export-dir': string;
}
export default class WorkerDeploy extends EasCommand {
static override description = 'deploy an Expo web build';
static override description = 'Deploy your Expo web build';
static override aliases = ['deploy'];
static override usage = [chalk`deploy {dim [options]}`, `deploy --prod`];
// TODO(@kitten): Keep command hidden until worker deployments are live
static override hidden = true;
static override state = 'beta';
static override flags = {
prod: Flags.boolean({
aliases: ['production'],
description: 'Create a new production deployment',
default: false,
}),
alias: Flags.string({
description: 'Custom alias to assign to the new deployment',
helpValue: 'name',
}),
id: Flags.string({
description: 'Custom unique identifier for the new deployment',
helpValue: 'xyz123',
}),
'export-dir': Flags.string({
description: 'Directory where the Expo project was exported',
helpValue: 'dir',
default: 'dist',
}),
// TODO(@kitten): Allow deployment identifier to be specified
...EasNonInteractiveAndJsonFlags,
...EASEnvironmentFlag,
};
static override contextDefinition = {
@@ -35,70 +93,47 @@ export default class WorkerDeploy extends EasCommand {
};
async runAsync(): Promise<void> {
Log.warn('EAS Worker Deployments are in beta and subject to breaking changes.');
// NOTE(cedric): `Log.warn` uses `console.log`, which is incorrect when running with `--json`
// eslint-disable-next-line no-console
console.warn(
chalk.yellow('EAS Worker Deployments are in beta and subject to breaking changes.')
);
const { flags: rawFlags } = await this.parse(WorkerDeploy);
const flags = this.sanitizeFlags(rawFlags);
if (flags.json) {
enableJsonOutput();
}
const {
getDynamicPrivateProjectConfigAsync,
loggedIn: { graphqlClient },
} = await this.getContextAsync(WorkerDeploy, {
nonInteractive: true,
});
projectDir,
} = await this.getContextAsync(WorkerDeploy, flags);
const { projectId, projectDir, exp } = await getDynamicPrivateProjectConfigAsync();
const distPath = path.resolve(projectDir, 'dist');
const [{ projectId }, projectDist] = await Promise.all([
getDynamicPrivateProjectConfigAsync(),
resolveExportedProjectAsync(flags, projectDir),
]);
let distServerPath: string | null;
let distClientPath: string;
if (exp.web?.output === 'static') {
distClientPath = distPath;
distServerPath = null;
if (!(await isDirectory(distClientPath))) {
throw new Error(
`No "dist/" folder found. Prepare your project for deployment with "npx expo export"`
);
}
Log.log('Detected "static" worker deployment');
} else if (exp.web?.output === 'server') {
distClientPath = path.resolve(distPath, 'client');
distServerPath = path.resolve(distPath, 'server');
if (!(await isDirectory(distClientPath))) {
throw new Error(
`No "dist/client/" folder found. Prepare your project for deployment with "npx expo export"`
);
} else if (!(await isDirectory(distServerPath))) {
throw new Error(
`No "dist/server/" folder found. Prepare your project for deployment with "npx expo export"`
);
}
Log.log('Detected "server" worker deployment');
} else {
throw new Error(
`Single-page apps are not supported. Ensure that app.json key "expo.web.output" is set to "server" or "static".`
);
}
logExportedProjectInfo(projectDist);
async function* emitWorkerTarballAsync(
assetMap: WorkerAssets.AssetMap
): AsyncGenerator<WorkerAssets.FileEntry> {
yield ['assets.json', JSON.stringify(assetMap)];
// TODO: Create manifest from user configuration
const manifest = { env: {} };
yield ['manifest.json', JSON.stringify(manifest)];
if (distServerPath) {
const workerFiles = WorkerAssets.listWorkerFilesAsync(distServerPath);
async function* emitWorkerTarballAsync(params: {
assetMap: WorkerAssets.AssetMap;
manifest: WorkerAssets.Manifest;
}): AsyncGenerator<WorkerAssets.FileEntry> {
yield ['assets.json', JSON.stringify(params.assetMap)];
yield ['manifest.json', JSON.stringify(params.manifest)];
if (projectDist.type === 'server' && projectDist.serverPath) {
const workerFiles = WorkerAssets.listWorkerFilesAsync(projectDist.serverPath);
for await (const workerFile of workerFiles) {
yield [`server/${workerFile.normalizedPath}`, workerFile.data];
}
}
}
async function uploadTarballAsync(tarPath: string): Promise<any> {
const uploadUrl = await getSignedDeploymentUrlAsync(graphqlClient, exp, {
appId: projectId,
});
async function uploadTarballAsync(tarPath: string, uploadUrl: string): Promise<any> {
const { response } = await uploadAsync({
url: uploadUrl,
filePath: tarPath,
@@ -110,7 +145,10 @@ export default class WorkerDeploy extends EasCommand {
if (response.status === 413) {
throw new Error(
'Upload failed! (Payload too large)\n' +
`The files in "dist/server/" (at: ${distServerPath}) exceed the maximum file size (10MB gzip).`
`The files in "${path.relative(
projectDir,
projectDist.path
)}" (at: ${projectDir}) exceed the maximum file size (10MB gzip).`
);
} else if (!response.ok) {
throw new Error(`Upload failed! (${response.statusText})`);
@@ -133,7 +171,8 @@ export default class WorkerDeploy extends EasCommand {
// TODO(@kitten): Batch and upload multiple files in parallel
const uploadParams: UploadParams[] = [];
for await (const asset of WorkerAssets.listAssetMapFilesAsync(distClientPath, assetMap)) {
const assetPath = projectDist.type === 'server' ? projectDist.clientPath : projectDist.path;
for await (const asset of WorkerAssets.listAssetMapFilesAsync(assetPath, assetMap)) {
const uploadURL = uploads[asset.normalizedPath];
if (uploadURL) {
uploadParams.push({ url: uploadURL, filePath: asset.path });
@@ -154,9 +193,9 @@ export default class WorkerDeploy extends EasCommand {
const details = chalk.dim(
`(${progress.pending} Pending, ${progress.transferred} Completed, ${progress.total} Total)`
);
return `Uploading client assets: ${percent.padStart(3)}% ${details}`;
return `Uploading assets: ${percent.padStart(3)}% ${details}`;
},
completedMessage: 'Uploaded assets for serverless deployment',
completedMessage: 'Uploaded assets',
});
try {
@@ -176,37 +215,174 @@ export default class WorkerDeploy extends EasCommand {
updateProgress({ isComplete: true });
}
let progress = ora('Preparing worker upload');
let assetMap: WorkerAssets.AssetMap;
let tarPath: string;
try {
assetMap = await WorkerAssets.createAssetMapAsync(distClientPath);
tarPath = await WorkerAssets.packFilesIterableAsync(emitWorkerTarballAsync(assetMap));
} catch (error: any) {
progress.fail('Failed to prepare worker upload');
throw error;
}
progress.succeed('Prepared worker upload');
progress = ora('Creating worker deployment');
let deployResult: any;
let progress = ora('Preparing project').start();
try {
deployResult = await uploadTarballAsync(tarPath);
const manifest = await WorkerAssets.createManifestAsync(
{
environment: flags.environment,
projectDir,
projectId,
},
graphqlClient
);
assetMap = await WorkerAssets.createAssetMapAsync(
projectDist.type === 'server' ? projectDist.clientPath : projectDist.path
);
tarPath = await WorkerAssets.packFilesIterableAsync(
emitWorkerTarballAsync({
assetMap,
manifest,
})
);
const uploadUrl = await getSignedDeploymentUrlAsync(graphqlClient, {
appId: projectId,
deploymentIdentifier: flags.deploymentIdentifier,
// NOTE(cedric): this function might ask the user for a dev-domain name,
// when that happens, no ora spinner should be running.
onSetupDevDomain: () => progress.stop(),
nonInteractive: flags.nonInteractive,
});
progress.start('Creating deployment');
deployResult = await uploadTarballAsync(tarPath, uploadUrl);
progress.succeed('Created deployment');
} catch (error: any) {
progress.fail('Failed to create worker deployment');
progress.fail('Failed to create deployment');
throw error;
}
progress.succeed('Created worker deployment');
await uploadAssetsAsync(assetMap, deployResult.uploads);
const baseDomain = process.env.EXPO_STAGING ? 'staging.expo' : 'expo';
const deploymentURL = `https://${deployResult.fullName}.${baseDomain}.app`;
const deploymentsUrl = `https://${baseDomain}.dev/accounts/${exp.owner}/projects/${deployResult.name}/serverless/deployments`;
let deploymentAlias: null | Awaited<ReturnType<typeof assignWorkerDeploymentAliasAsync>> = null;
if (flags.aliasName) {
progress = ora(chalk`Assigning alias {bold ${flags.aliasName}} to deployment`).start();
try {
deploymentAlias = await assignWorkerDeploymentAliasAsync({
graphqlClient,
appId: projectId,
deploymentId: deployResult.id,
aliasName: flags.aliasName,
});
// Only stop the spinner when not promoting to production
if (!flags.isProduction) {
progress.succeed(chalk`Assigned alias {bold ${flags.aliasName}} to deployment`);
}
} catch (error: any) {
progress.fail(chalk`Failed to assign {bold ${flags.aliasName}} alias to deployment`);
throw error;
}
}
let deploymentProdAlias: null | Awaited<
ReturnType<typeof assignWorkerDeploymentProductionAsync>
> = null;
if (flags.isProduction) {
try {
if (!flags.aliasName) {
progress = ora(chalk`Promoting deployment to {bold production}`).start();
} else {
progress.text = chalk`Promoting deployment to {bold production}`;
}
deploymentProdAlias = await assignWorkerDeploymentProductionAsync({
graphqlClient,
appId: projectId,
deploymentId: deployResult.id,
});
progress.succeed(
!flags.aliasName
? chalk`Promoted deployment to {bold production}`
: chalk`Promoted deployment to {bold production} with alias {bold ${flags.aliasName}}`
);
} catch (error: any) {
progress.fail('Failed to promote deployment to production');
throw error;
}
}
if (flags.json) {
printJsonOnlyOutput(
formatWorkerDeploymentJson({
projectId,
deployment: {
deploymentIdentifier: deployResult.id,
url: getDeploymentUrlFromFullName(deployResult.fullName),
},
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
production: deploymentProdAlias,
})
);
return;
}
Log.addNewLineIfNone();
Log.log(`🎉 Your worker deployment is ready: ${deploymentURL}`);
Log.log(`🎉 Your deployment is ready`);
Log.addNewLineIfNone();
Log.log(`🔗 Manage on EAS: ${deploymentsUrl}`);
Log.log(
formatWorkerDeploymentTable({
projectId,
deployment: {
deploymentIdentifier: deployResult.id,
url: getDeploymentUrlFromFullName(deployResult.fullName),
},
aliases: [deploymentAlias].filter(Boolean) as WorkerDeploymentAliasFragment[],
production: deploymentProdAlias,
})
);
if (!deploymentProdAlias) {
Log.addNewLineIfNone();
Log.log('🚀 When you are ready to deploy to production:');
Log.log(chalk` $ eas deploy {bold --prod}`);
}
}
private sanitizeFlags(flags: RawDeployFlags): DeployFlags {
return {
nonInteractive: flags['non-interactive'],
json: flags['json'],
isProduction: !!flags.prod,
aliasName: flags.alias?.trim().toLowerCase(),
deploymentIdentifier: flags.id?.trim(),
exportDir: flags['export-dir'],
};
}
}
async function resolveExportedProjectAsync(
flags: DeployFlags,
projectDir: string
): Promise<
| { type: 'static'; modifiedAt: Date; path: string }
| { type: 'server'; modifiedAt: Date; path: string; serverPath: string; clientPath: string }
> {
const exportPath = path.join(projectDir, flags.exportDir);
const serverPath = path.join(exportPath, 'server');
const clientPath = path.join(exportPath, 'client');
const [hasServerPath, hasClientPath, modifiedAt] = await Promise.all([
isDirectory(serverPath),
isDirectory(clientPath),
fs.promises.stat(exportPath).then(stat => stat.mtime),
]);
if (hasServerPath && hasClientPath) {
return { type: 'server', path: exportPath, modifiedAt, serverPath, clientPath };
}
return { type: 'static', path: exportPath, modifiedAt };
}
function logExportedProjectInfo(
project: Awaited<ReturnType<typeof resolveExportedProjectAsync>>
): void {
const modifiedAgo = formatTimeAgo(project.modifiedAt);
Log.log(chalk`{dim > Project export: ${project.type} - created ${modifiedAgo}}`);
}
+355 -169
View File
@@ -1333,6 +1333,7 @@ export type App = Project & {
/** EAS Submissions associated with this app */
submissions: Array<Submission>;
submissionsPaginated: AppSubmissionsConnection;
suggestedDevDomainName: Scalars['String']['output'];
/** Coalesced project activity for an app using pagination */
timelineActivity: TimelineActivityConnection;
/** @deprecated 'likes' have been deprecated. */
@@ -1365,11 +1366,10 @@ export type App = Project & {
workerDeployment?: Maybe<WorkerDeployment>;
workerDeploymentAlias?: Maybe<WorkerDeploymentAlias>;
workerDeploymentAliases: WorkerDeploymentAliasesConnection;
workerDeploymentRequest: WorkerDeploymentRequestEdge;
workerDeployments: WorkerDeploymentsConnection;
workerDeploymentsCrash: WorkerDeploymentCrashEdge;
workerDeploymentsCrashes?: Maybe<WorkerDeploymentCrashes>;
workerDeploymentsMetrics?: Maybe<WorkerDeploymentMetrics>;
workerDeploymentsRequest: WorkerDeploymentRequestEdge;
workerDeploymentsRequests?: Maybe<WorkerDeploymentRequests>;
};
@@ -1608,12 +1608,6 @@ export type AppWorkerDeploymentAliasesArgs = {
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppWorkerDeploymentRequestArgs = {
requestId: Scalars['ID']['input'];
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppWorkerDeploymentsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
@@ -1638,16 +1632,14 @@ export type AppWorkerDeploymentsCrashesArgs = {
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppWorkerDeploymentsMetricsArgs = {
filters?: InputMaybe<MetricsFilters>;
timespan: MetricsTimespan;
export type AppWorkerDeploymentsRequestArgs = {
requestKey: Scalars['ID']['input'];
};
/** Represents an Exponent App (or Experience in legacy terms) */
export type AppWorkerDeploymentsRequestsArgs = {
filter?: InputMaybe<WorkerDeploymentRequestsFilter>;
limit?: Scalars['Int']['input'];
filters?: InputMaybe<RequestsFilters>;
timespan: RequestsTimespan;
};
@@ -2505,6 +2497,8 @@ export type AuditLogExportInput = {
createdAfter: Scalars['String']['input'];
createdBefore: Scalars['String']['input'];
format: AuditLogsExportFormat;
targetEntityMutationType?: InputMaybe<Array<TargetEntityMutationType>>;
targetEntityTypeName?: InputMaybe<Array<EntityTypeName>>;
};
export type AuditLogFilterInput = {
@@ -2586,6 +2580,7 @@ export type BackgroundJobReceiptQueryByIdArgs = {
export enum BackgroundJobResultType {
AuditLogsExport = 'AUDIT_LOGS_EXPORT',
GithubBuild = 'GITHUB_BUILD',
UserAuditLogsExport = 'USER_AUDIT_LOGS_EXPORT',
Void = 'VOID'
}
@@ -2643,6 +2638,7 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
buildProfile?: Maybe<Scalars['String']['output']>;
canRetry: Scalars['Boolean']['output'];
cancelingActor?: Maybe<Actor>;
/** @deprecated Use 'updateChannel' field instead. */
channel?: Maybe<Scalars['String']['output']>;
childBuild?: Maybe<Build>;
completedAt?: Maybe<Scalars['DateTime']['output']>;
@@ -2699,12 +2695,13 @@ export type Build = ActivityTimelineProjectActivity & BuildOrBuildJob & {
retryDisabledReason?: Maybe<BuildRetryDisabledReason>;
runFromCI?: Maybe<Scalars['Boolean']['output']>;
runtime?: Maybe<Runtime>;
/** @deprecated Use 'runtime' field . */
/** @deprecated Use 'runtime' field instead. */
runtimeVersion?: Maybe<Scalars['String']['output']>;
sdkVersion?: Maybe<Scalars['String']['output']>;
selectedImage?: Maybe<Scalars['String']['output']>;
status: BuildStatus;
submissions: Array<Submission>;
updateChannel?: Maybe<UpdateChannel>;
updatedAt: Scalars['DateTime']['output'];
workerStartedAt?: Maybe<Scalars['DateTime']['output']>;
};
@@ -3388,6 +3385,7 @@ export type CustomDomainDnsRecord = {
};
export enum CustomDomainDnsRecordType {
A = 'A',
Cname = 'CNAME',
Txt = 'TXT'
}
@@ -3824,8 +3822,6 @@ export enum EntityTypeName {
Customer = 'Customer',
GoogleServiceAccountKey = 'GoogleServiceAccountKey',
IosAppCredentials = 'IosAppCredentials',
TurtleBuild = 'TurtleBuild',
Update = 'Update',
UserInvitation = 'UserInvitation',
UserPermission = 'UserPermission'
}
@@ -5104,47 +5100,6 @@ export type MeteredBillingStatus = {
EAS_UPDATE: Scalars['Boolean']['output'];
};
export enum MetricsCacheStatus {
Hit = 'HIT',
Miss = 'MISS',
Pass = 'PASS'
}
export type MetricsFilters = {
cacheStatus?: InputMaybe<Array<MetricsCacheStatus>>;
continent?: InputMaybe<Array<ContinentCode>>;
hasCustomDomainOrigin?: InputMaybe<Scalars['Boolean']['input']>;
isAsset?: InputMaybe<Scalars['Boolean']['input']>;
isCrash?: InputMaybe<Scalars['Boolean']['input']>;
isVerifiedBot?: InputMaybe<Scalars['Boolean']['input']>;
method?: InputMaybe<Array<MetricsRequestMethod>>;
os?: InputMaybe<Array<UserAgentOs>>;
pathname?: InputMaybe<Scalars['String']['input']>;
status?: InputMaybe<Array<Scalars['Int']['input']>>;
statusType?: InputMaybe<Array<MetricsStatusType>>;
};
export enum MetricsRequestMethod {
Delete = 'DELETE',
Get = 'GET',
Options = 'OPTIONS',
Post = 'POST',
Put = 'PUT'
}
export enum MetricsStatusType {
ClientError = 'CLIENT_ERROR',
None = 'NONE',
Redirect = 'REDIRECT',
ServerError = 'SERVER_ERROR',
Successful = 'SUCCESSFUL'
}
export type MetricsTimespan = {
end: Scalars['DateTime']['input'];
start: Scalars['DateTime']['input'];
};
export type Notification = {
__typename?: 'Notification';
accountName: Scalars['String']['output'];
@@ -5379,16 +5334,34 @@ export type PublishUpdateGroupInput = {
updateInfoGroup?: InputMaybe<UpdateInfoGroup>;
};
export enum RequestStatusPattern {
Http_2Xx = 'HTTP_2XX',
Http_3Xx = 'HTTP_3XX',
Http_4Xx = 'HTTP_4XX',
Http_5Xx = 'HTTP_5XX'
export enum RequestMethod {
Delete = 'DELETE',
Get = 'GET',
Head = 'HEAD',
Options = 'OPTIONS',
Patch = 'PATCH',
Post = 'POST',
Put = 'PUT'
}
export type RequestsFilters = {
cacheStatus?: InputMaybe<Array<ResponseCacheStatus>>;
continent?: InputMaybe<Array<ContinentCode>>;
hasCustomDomainOrigin?: InputMaybe<Scalars['Boolean']['input']>;
isAsset?: InputMaybe<Scalars['Boolean']['input']>;
isCrash?: InputMaybe<Scalars['Boolean']['input']>;
isVerifiedBot?: InputMaybe<Scalars['Boolean']['input']>;
method?: InputMaybe<Array<RequestMethod>>;
os?: InputMaybe<Array<UserAgentOs>>;
pathname?: InputMaybe<Scalars['String']['input']>;
responseType?: InputMaybe<Array<ResponseType>>;
status?: InputMaybe<Array<Scalars['Int']['input']>>;
statusType?: InputMaybe<Array<ResponseStatusType>>;
};
export type RequestsTimespan = {
end: Scalars['DateTime']['input'];
start?: InputMaybe<Scalars['DateTime']['input']>;
start: Scalars['DateTime']['input'];
};
export type RescindUserInvitationResult = {
@@ -5401,6 +5374,27 @@ export enum ResourceClassExperiment {
N2 = 'N2'
}
export enum ResponseCacheStatus {
Hit = 'HIT',
Miss = 'MISS',
Pass = 'PASS'
}
export enum ResponseStatusType {
ClientError = 'CLIENT_ERROR',
None = 'NONE',
Redirect = 'REDIRECT',
ServerError = 'SERVER_ERROR',
Successful = 'SUCCESSFUL'
}
export enum ResponseType {
Asset = 'ASSET',
Crash = 'CRASH',
Rejected = 'REJECTED',
Route = 'ROUTE'
}
/** Represents a robot (not human) actor. */
export type Robot = Actor & {
__typename?: 'Robot';
@@ -5569,6 +5563,7 @@ export type RootMutation = {
uploadSession: UploadSession;
/** Mutations that create, update, and delete pinned apps */
userAppPins: UserAppPinMutation;
userAuditLog: UserAuditLogMutation;
/** Mutations that create, delete, and accept UserInvitations */
userInvitation: UserInvitationMutation;
/** Mutations that create, delete, update Webhooks */
@@ -5624,7 +5619,7 @@ export type RootQuery = {
/** Top-level query object for querying Apple Teams. */
appleTeam: AppleTeamQuery;
asset: AssetQuery;
/** Top-level query object for querying Audit Logs. */
/** Top-level query object for querying Account Audit Logs. */
auditLogs: AuditLogQuery;
backgroundJobReceipt: BackgroundJobReceiptQuery;
/** Top-level query object for querying Branchs. */
@@ -5684,6 +5679,8 @@ export type RootQuery = {
userActor: UserActorQuery;
/** Top-level query object for querying UserActorPublicData publicly. */
userActorPublicData: UserActorPublicDataQuery;
/** Top-level query object for querying User Audit Logs. */
userAuditLogs: UserAuditLogQuery;
/** @deprecated Use 'byId' field under 'user'. */
userByUserId?: Maybe<User>;
/** @deprecated Use 'byUsername' field under 'user'. */
@@ -5731,12 +5728,56 @@ export type RootQueryUserByUsernameArgs = {
export type Runtime = {
__typename?: 'Runtime';
app: App;
builds: AppBuildsConnection;
createdAt: Scalars['DateTime']['output'];
deployments: DeploymentsConnection;
fingerprintDebugInfoUrl?: Maybe<Scalars['String']['output']>;
firstBuildCreatedAt: Scalars['DateTime']['output'];
firstBuildCreatedAt?: Maybe<Scalars['DateTime']['output']>;
id: Scalars['ID']['output'];
updatedAt: Scalars['DateTime']['output'];
updates: AppUpdatesConnection;
version: Scalars['String']['output'];
};
export type RuntimeBuildsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<RuntimeBuildsFilterInput>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type RuntimeDeploymentsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<RuntimeDeploymentsFilterInput>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type RuntimeUpdatesArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type RuntimeBuildsFilterInput = {
channel?: InputMaybe<Scalars['String']['input']>;
developmentClient?: InputMaybe<Scalars['Boolean']['input']>;
distributions?: InputMaybe<Array<DistributionType>>;
platforms?: InputMaybe<Array<AppPlatform>>;
releaseChannel?: InputMaybe<Scalars['String']['input']>;
simulator?: InputMaybe<Scalars['Boolean']['input']>;
};
export type RuntimeDeploymentsFilterInput = {
channel?: InputMaybe<Scalars['String']['input']>;
};
export type RuntimeEdge = {
__typename?: 'RuntimeEdge';
cursor: Scalars['String']['output'];
@@ -6312,6 +6353,7 @@ export type Update = ActivityTimelineProjectActivity & {
branchId: Scalars['ID']['output'];
codeSigningInfo?: Maybe<CodeSigningInfo>;
createdAt: Scalars['DateTime']['output'];
deployments: UpdateDeploymentsConnection;
expoGoSDKVersion?: Maybe<Scalars['String']['output']>;
gitCommitHash?: Maybe<Scalars['String']['output']>;
group: Scalars['String']['output'];
@@ -6333,6 +6375,14 @@ export type Update = ActivityTimelineProjectActivity & {
updatedAt: Scalars['DateTime']['output'];
};
export type UpdateDeploymentsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};
export type UpdateBranch = {
__typename?: 'UpdateBranch';
app: App;
@@ -6462,6 +6512,18 @@ export type UpdateChannelMutationEditUpdateChannelArgs = {
channelId: Scalars['ID']['input'];
};
export type UpdateDeploymentEdge = {
__typename?: 'UpdateDeploymentEdge';
cursor: Scalars['String']['output'];
node: Deployment;
};
export type UpdateDeploymentsConnection = {
__typename?: 'UpdateDeploymentsConnection';
edges: Array<UpdateDeploymentEdge>;
pageInfo: PageInfo;
};
export type UpdateGitHubBuildTriggerInput = {
autoSubmit: Scalars['Boolean']['input'];
buildProfile: Scalars['String']['input'];
@@ -6931,6 +6993,84 @@ export type UserAppPinMutationUnpinAppArgs = {
appId: Scalars['ID']['input'];
};
export type UserAuditLog = {
__typename?: 'UserAuditLog';
actor: Actor;
createdAt: Scalars['DateTime']['output'];
id: Scalars['ID']['output'];
ip?: Maybe<Scalars['String']['output']>;
metadata?: Maybe<Scalars['JSONObject']['output']>;
targetEntityId: Scalars['ID']['output'];
targetEntityMutationType: TargetEntityMutationType;
targetEntityTypeName: Scalars['String']['output'];
user: User;
websiteMessage: Scalars['String']['output'];
};
export type UserAuditLogConnection = {
__typename?: 'UserAuditLogConnection';
edges: Array<UserAuditLogEdge>;
pageInfo: PageInfo;
};
export type UserAuditLogEdge = {
__typename?: 'UserAuditLogEdge';
cursor: Scalars['String']['output'];
node: UserAuditLog;
};
export type UserAuditLogExportInput = {
createdAfter: Scalars['String']['input'];
createdBefore: Scalars['String']['input'];
format: AuditLogsExportFormat;
targetEntityMutationType?: InputMaybe<Array<TargetEntityMutationType>>;
targetEntityTypeName?: InputMaybe<Array<UserEntityTypeName>>;
userId: Scalars['ID']['input'];
};
export type UserAuditLogFilterInput = {
entityTypes?: InputMaybe<Array<UserEntityTypeName>>;
mutationTypes?: InputMaybe<Array<TargetEntityMutationType>>;
};
export type UserAuditLogMutation = {
__typename?: 'UserAuditLogMutation';
/** Exports User Audit Logs for an user. Returns the ID of the background job receipt. Use BackgroundJobReceiptQuery to get the status of the job. */
exportUserAuditLogs: BackgroundJobReceipt;
};
export type UserAuditLogMutationExportUserAuditLogsArgs = {
exportInput: UserAuditLogExportInput;
};
export type UserAuditLogQuery = {
__typename?: 'UserAuditLogQuery';
/** Query User Audit Logs by user ID */
byUserId: Array<UserAuditLog>;
/** Audit logs for user */
byUserIdPaginated: UserAuditLogConnection;
};
export type UserAuditLogQueryByUserIdArgs = {
limit: Scalars['Int']['input'];
offset: Scalars['Int']['input'];
targetEntityMutationType?: InputMaybe<Array<TargetEntityMutationType>>;
targetEntityTypeName?: InputMaybe<Array<UserEntityTypeName>>;
userId: Scalars['ID']['input'];
};
export type UserAuditLogQueryByUserIdPaginatedArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
filter?: InputMaybe<UserAuditLogFilterInput>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
userId: Scalars['ID']['input'];
};
export type UserDataInput = {
email?: InputMaybe<Scalars['String']['input']>;
firstName?: InputMaybe<Scalars['String']['input']>;
@@ -6941,6 +7081,17 @@ export type UserDataInput = {
username?: InputMaybe<Scalars['String']['input']>;
};
export enum UserEntityTypeName {
AccessToken = 'AccessToken',
DiscordUser = 'DiscordUser',
GitHubUser = 'GitHubUser',
Password = 'Password',
SsoUser = 'SSOUser',
User = 'User',
UserSecondFactorBackupCodes = 'UserSecondFactorBackupCodes',
UserSecondFactorDevice = 'UserSecondFactorDevice'
}
/** An pending invitation sent to an email granting membership on an Account. */
export type UserInvitation = {
__typename?: 'UserInvitation';
@@ -7244,8 +7395,9 @@ export type WorkerDeployment = {
deploymentIdentifier: Scalars['WorkerDeploymentIdentifier']['output'];
devDomainName: Scalars['DevDomainName']['output'];
id: Scalars['ID']['output'];
initiatingActor?: Maybe<Actor>;
logs?: Maybe<WorkerDeploymentLogs>;
metrics?: Maybe<WorkerDeploymentMetrics>;
requests?: Maybe<WorkerDeploymentRequests>;
subdomain: Scalars['String']['output'];
url: Scalars['String']['output'];
};
@@ -7257,9 +7409,9 @@ export type WorkerDeploymentLogsArgs = {
};
export type WorkerDeploymentMetricsArgs = {
filters?: InputMaybe<MetricsFilters>;
timespan: MetricsTimespan;
export type WorkerDeploymentRequestsArgs = {
filters?: InputMaybe<RequestsFilters>;
timespan: RequestsTimespan;
};
export type WorkerDeploymentAlias = {
@@ -7290,7 +7442,7 @@ export type WorkerDeploymentAliasesConnection = {
export type WorkerDeploymentCrashEdge = {
__typename?: 'WorkerDeploymentCrashEdge';
logs: Array<WorkerDeploymentLogNode>;
request: WorkerDeploymentRequestNode;
request?: Maybe<WorkerDeploymentRequestNode>;
sample: WorkerDeploymentCrashSample;
};
@@ -7347,30 +7499,69 @@ export type WorkerDeploymentLogs = {
nodes: Array<WorkerDeploymentLogNode>;
};
export type WorkerDeploymentMetrics = {
__typename?: 'WorkerDeploymentMetrics';
byBrowser: Array<WorkerDeploymentMetricsBrowserEdge>;
byContinent: Array<WorkerDeploymentMetricsContinentEdge>;
byOS: Array<WorkerDeploymentMetricsOperatingSystemEdge>;
export type WorkerDeploymentQuery = {
__typename?: 'WorkerDeploymentQuery';
byId: WorkerDeployment;
};
export type WorkerDeploymentQueryByIdArgs = {
id: Scalars['ID']['input'];
};
export type WorkerDeploymentRequestEdge = {
__typename?: 'WorkerDeploymentRequestEdge';
crash?: Maybe<WorkerDeploymentCrashSample>;
logs: Array<WorkerDeploymentLogNode>;
node: WorkerDeploymentRequestNode;
};
export type WorkerDeploymentRequestNode = {
__typename?: 'WorkerDeploymentRequestNode';
browserKind?: Maybe<UserAgentBrowser>;
browserVersion?: Maybe<Scalars['String']['output']>;
cacheStatus?: Maybe<ResponseCacheStatus>;
continent?: Maybe<ContinentCode>;
country?: Maybe<Scalars['String']['output']>;
deploymentIdentifier: Scalars['String']['output'];
duration: Scalars['Int']['output'];
hasCustomDomainOrigin: Scalars['Boolean']['output'];
isAsset: Scalars['Boolean']['output'];
isCrash: Scalars['Boolean']['output'];
isRejected: Scalars['Boolean']['output'];
isStaleIfError: Scalars['Boolean']['output'];
isStaleWhileRevalidate: Scalars['Boolean']['output'];
isVerifiedBot: Scalars['Boolean']['output'];
key: Scalars['ID']['output'];
method: Scalars['String']['output'];
os?: Maybe<UserAgentOs>;
pathname: Scalars['String']['output'];
region?: Maybe<Scalars['String']['output']>;
requestTimestamp: Scalars['DateTime']['output'];
responseType: ResponseType;
scriptName: Scalars['String']['output'];
search?: Maybe<Scalars['String']['output']>;
status: Scalars['Int']['output'];
statusType?: Maybe<ResponseStatusType>;
};
export type WorkerDeploymentRequests = {
__typename?: 'WorkerDeploymentRequests';
byBrowser: Array<WorkerDeploymentRequestsBrowserEdge>;
byCacheStatus: Array<WorkerDeploymentRequestsCacheStatusEdge>;
byContinent: Array<WorkerDeploymentRequestsContinentEdge>;
byMethod: Array<WorkerDeploymentRequestsMethodEdge>;
byOS: Array<WorkerDeploymentRequestsOperatingSystemEdge>;
byStatusType: Array<WorkerDeploymentRequestsStatusTypeEdge>;
interval: Scalars['Int']['output'];
summary: WorkerDeploymentMetricsNode;
timeseries: Array<WorkerDeploymentMetricsTimeseriesEdge>;
minRowsWithoutLimit: Scalars['Int']['output'];
nodes: Array<WorkerDeploymentRequestNode>;
summary: WorkerDeploymentRequestsAggregationNode;
timeseries: Array<WorkerDeploymentRequestsTimeseriesEdge>;
};
export type WorkerDeploymentMetricsBrowserEdge = {
__typename?: 'WorkerDeploymentMetricsBrowserEdge';
browser?: Maybe<UserAgentBrowser>;
node: WorkerDeploymentMetricsNode;
};
export type WorkerDeploymentMetricsContinentEdge = {
__typename?: 'WorkerDeploymentMetricsContinentEdge';
continent: ContinentCode;
node: WorkerDeploymentMetricsNode;
};
export type WorkerDeploymentMetricsNode = {
__typename?: 'WorkerDeploymentMetricsNode';
export type WorkerDeploymentRequestsAggregationNode = {
__typename?: 'WorkerDeploymentRequestsAggregationNode';
assetsPerMs?: Maybe<Scalars['Float']['output']>;
assetsSum: Scalars['Int']['output'];
cacheHitRatio: Scalars['Float']['output'];
@@ -7410,90 +7601,54 @@ export type WorkerDeploymentMetricsNode = {
staleWhileRevalidateSum: Scalars['Int']['output'];
};
export type WorkerDeploymentMetricsOperatingSystemEdge = {
__typename?: 'WorkerDeploymentMetricsOperatingSystemEdge';
node: WorkerDeploymentMetricsNode;
os?: Maybe<UserAgentOs>;
};
export type WorkerDeploymentMetricsTimeseriesEdge = {
__typename?: 'WorkerDeploymentMetricsTimeseriesEdge';
byBrowser: Array<WorkerDeploymentMetricsBrowserEdge>;
byContinent: Array<WorkerDeploymentMetricsContinentEdge>;
byOS: Array<WorkerDeploymentMetricsOperatingSystemEdge>;
node?: Maybe<WorkerDeploymentMetricsNode>;
timestamp: Scalars['DateTime']['output'];
};
export type WorkerDeploymentQuery = {
__typename?: 'WorkerDeploymentQuery';
byId: WorkerDeployment;
};
export type WorkerDeploymentQueryByIdArgs = {
id: Scalars['ID']['input'];
};
export type WorkerDeploymentRequestEdge = {
__typename?: 'WorkerDeploymentRequestEdge';
crash?: Maybe<WorkerDeploymentCrashSample>;
logs: Array<WorkerDeploymentLogNode>;
node: WorkerDeploymentRequestNode;
};
export enum WorkerDeploymentRequestKind {
Asset = 'ASSET',
Crash = 'CRASH',
Rejected = 'REJECTED'
}
export type WorkerDeploymentRequestLocation = {
__typename?: 'WorkerDeploymentRequestLocation';
continent?: Maybe<ContinentCode>;
countryCode?: Maybe<Scalars['String']['output']>;
regionCode?: Maybe<Scalars['String']['output']>;
};
export type WorkerDeploymentRequestNode = {
__typename?: 'WorkerDeploymentRequestNode';
export type WorkerDeploymentRequestsBrowserEdge = {
__typename?: 'WorkerDeploymentRequestsBrowserEdge';
browser?: Maybe<UserAgentBrowser>;
browserVersion?: Maybe<Scalars['String']['output']>;
hasCustomDomainOrigin: Scalars['Boolean']['output'];
id: Scalars['ID']['output'];
isVerifiedBot: Scalars['Boolean']['output'];
kind?: Maybe<WorkerDeploymentRequestKind>;
location?: Maybe<WorkerDeploymentRequestLocation>;
node: WorkerDeploymentRequestsAggregationNode;
};
export type WorkerDeploymentRequestsCacheStatusEdge = {
__typename?: 'WorkerDeploymentRequestsCacheStatusEdge';
cacheStatus?: Maybe<ResponseCacheStatus>;
node: WorkerDeploymentRequestsAggregationNode;
};
export type WorkerDeploymentRequestsContinentEdge = {
__typename?: 'WorkerDeploymentRequestsContinentEdge';
continent: ContinentCode;
node: WorkerDeploymentRequestsAggregationNode;
};
export type WorkerDeploymentRequestsMethodEdge = {
__typename?: 'WorkerDeploymentRequestsMethodEdge';
method: Scalars['String']['output'];
node: WorkerDeploymentRequestsAggregationNode;
};
export type WorkerDeploymentRequestsOperatingSystemEdge = {
__typename?: 'WorkerDeploymentRequestsOperatingSystemEdge';
node: WorkerDeploymentRequestsAggregationNode;
os?: Maybe<UserAgentOs>;
pathname: Scalars['String']['output'];
scriptName: Scalars['String']['output'];
search?: Maybe<Scalars['String']['output']>;
status: Scalars['Int']['output'];
};
export type WorkerDeploymentRequestsStatusTypeEdge = {
__typename?: 'WorkerDeploymentRequestsStatusTypeEdge';
node: WorkerDeploymentRequestsAggregationNode;
statusType?: Maybe<ResponseStatusType>;
};
export type WorkerDeploymentRequestsTimeseriesEdge = {
__typename?: 'WorkerDeploymentRequestsTimeseriesEdge';
byBrowser: Array<WorkerDeploymentRequestsBrowserEdge>;
byCacheStatus: Array<WorkerDeploymentRequestsCacheStatusEdge>;
byContinent: Array<WorkerDeploymentRequestsContinentEdge>;
byMethod: Array<WorkerDeploymentRequestsMethodEdge>;
byOS: Array<WorkerDeploymentRequestsOperatingSystemEdge>;
byStatusType: Array<WorkerDeploymentRequestsStatusTypeEdge>;
node?: Maybe<WorkerDeploymentRequestsAggregationNode>;
timestamp: Scalars['DateTime']['output'];
wallTime: Scalars['Int']['output'];
};
export type WorkerDeploymentRequests = {
__typename?: 'WorkerDeploymentRequests';
minRowsWithoutLimit?: Maybe<Scalars['Int']['output']>;
nodes: Array<WorkerDeploymentRequestNode>;
};
export type WorkerDeploymentRequestsFilter = {
include?: InputMaybe<WorkerDeploymentRequestsInclude>;
includeBotRequests?: InputMaybe<Scalars['Boolean']['input']>;
methods?: InputMaybe<Array<Scalars['String']['input']>>;
pathname?: InputMaybe<Scalars['String']['input']>;
statusCodes?: InputMaybe<Array<Scalars['Int']['input']>>;
statusPatterns?: InputMaybe<Array<RequestStatusPattern>>;
};
export enum WorkerDeploymentRequestsInclude {
Assets = 'ASSETS',
Routes = 'ROUTES'
}
export type WorkerDeploymentsConnection = {
__typename?: 'WorkerDeploymentsConnection';
edges: Array<WorkerDeploymentEdge>;
@@ -8563,6 +8718,10 @@ export type CommonIosAppCredentialsWithoutBuildCredentialsFragment = { __typenam
export type CommonIosAppCredentialsFragment = { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any }> } | null }>, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, name: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, githubRepository?: { __typename?: 'GitHubRepository', id: string, metadata: { __typename?: 'GitHubRepositoryMetadata', githubRepoOwnerName: string, githubRepoName: string } } | null }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null };
export type WorkerDeploymentFragment = { __typename?: 'WorkerDeployment', id: string, url: string, deploymentIdentifier: any, deploymentDomain: string, createdAt: any };
export type WorkerDeploymentAliasFragment = { __typename?: 'WorkerDeploymentAlias', id: string, aliasName?: any | null, url: string };
export type CreateDeploymentUrlMutationVariables = Exact<{
appId: Scalars['ID']['input'];
deploymentIdentifier?: InputMaybe<Scalars['ID']['input']>;
@@ -8578,3 +8737,30 @@ export type AssignDevDomainNameMutationVariables = Exact<{
export type AssignDevDomainNameMutation = { __typename?: 'RootMutation', devDomainName: { __typename?: 'AppDevDomainNameMutation', assignDevDomainName: { __typename?: 'AppDevDomainName', id: string, name: any } } };
export type AssignAliasMutationVariables = Exact<{
appId: Scalars['ID']['input'];
deploymentId: Scalars['ID']['input'];
aliasName?: InputMaybe<Scalars['WorkerDeploymentIdentifier']['input']>;
}>;
export type AssignAliasMutation = { __typename?: 'RootMutation', deployments: { __typename?: 'DeploymentsMutation', assignAlias: { __typename?: 'WorkerDeploymentAlias', id: string, aliasName?: any | null, url: string, workerDeployment: { __typename?: 'WorkerDeployment', id: string, url: string, deploymentIdentifier: any, deploymentDomain: string, createdAt: any } } } };
export type PaginatedWorkerDeploymentsQueryVariables = Exact<{
appId: Scalars['String']['input'];
first?: InputMaybe<Scalars['Int']['input']>;
after?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
}>;
export type PaginatedWorkerDeploymentsQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, workerDeployments: { __typename?: 'WorkerDeploymentsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null }, edges: Array<{ __typename?: 'WorkerDeploymentEdge', cursor: string, node: { __typename?: 'WorkerDeployment', id: string, url: string, deploymentIdentifier: any, deploymentDomain: string, createdAt: any } }> } } } };
export type SuggestedDevDomainNameQueryVariables = Exact<{
appId: Scalars['String']['input'];
}>;
export type SuggestedDevDomainNameQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byId: { __typename?: 'App', id: string, suggestedDevDomainName: string } } };
@@ -18,6 +18,7 @@ export type PublicExpoConfig = Omit<
export interface ExpoConfigOptions {
env?: Env;
skipSDKVersionRequirement?: boolean;
skipPlugins?: boolean;
}
interface ExpoConfigOptionsInternal extends ExpoConfigOptions {
@@ -52,6 +53,7 @@ function getExpoConfigInternal(
const { exp } = getConfig(projectDir, {
skipSDKVersionRequirement: true,
...(opts.isPublicConfig ? { isPublicConfig: true } : {}),
...(opts.skipPlugins ? { skipPlugins: true } : {}),
});
const { error } = MinimalAppConfigSchema.validate(exp, {
@@ -1,7 +1,14 @@
import { instance, mock } from 'ts-mockito';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { App, Runtime, UpdateBranch, UpdateChannel, UpdateInsights } from '../../graphql/generated';
import {
App,
Runtime,
UpdateBranch,
UpdateChannel,
UpdateDeploymentsConnection,
UpdateInsights,
} from '../../graphql/generated';
import { ChannelQuery } from '../../graphql/queries/ChannelQuery';
import { getBranchNameFromChannelNameAsync } from '../getBranchNameFromChannelNameAsync';
@@ -127,6 +134,7 @@ function mockUpdateBranches(branchNames: string[]): UpdateBranch[] {
runtimeVersion: '1.0.0',
runtime: {} as Runtime, // Temporary fix to resolve type errors
insights: {} as UpdateInsights, // Temporary fix to resolve type errors
deployments: {} as UpdateDeploymentsConnection, // Temporary fix to resolve type errors
platform: 'ios',
manifestFragment: '...',
isRollBackToEmbedded: false,
+38
View File
@@ -1,3 +1,4 @@
import { get as getEnv } from '@expo/env';
import { Gzip, GzipOptions } from 'minizlib';
import { HashOptions, createHash, randomBytes } from 'node:crypto';
import fs, { createWriteStream } from 'node:fs';
@@ -6,6 +7,10 @@ import path from 'node:path';
import { pipeline } from 'node:stream/promises';
import { pack } from 'tar-stream';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { EnvironmentVariableEnvironment } from '../graphql/generated';
import { EnvironmentVariablesQuery } from '../graphql/queries/EnvironmentVariablesQuery';
/** Returns whether a file or folder is ignored */
function isIgnoredName(name: string): boolean {
switch (name) {
@@ -87,6 +92,39 @@ async function createAssetMapAsync(
return map;
}
export interface Manifest {
env: Record<string, string | undefined>;
}
interface CreateManifestParams {
projectId: string;
projectDir: string;
environment?: EnvironmentVariableEnvironment;
}
/** Creates a manifest configuration sent up for deployment */
export async function createManifestAsync(
params: CreateManifestParams,
graphqlClient: ExpoGraphqlClient
): Promise<Manifest> {
let env: Record<string, string | undefined>;
if (params.environment) {
env = Object.fromEntries(
(
await EnvironmentVariablesQuery.byAppIdWithSensitiveAsync(graphqlClient, {
appId: params.projectId,
environment: params.environment,
})
).map(variable => [variable.name, variable.value ?? undefined])
);
} else {
// NOTE: This is required for the .env resolution
process.env.NODE_ENV = 'production';
env = getEnv(params.projectDir).env;
}
return { env };
}
interface WorkerFileEntry {
normalizedPath: string;
path: string;
+158 -23
View File
@@ -1,24 +1,32 @@
import { ExpoConfig } from '@expo/config-types';
import { CombinedError as GraphqlError } from '@urql/core';
import chalk from 'chalk';
import { DeploymentsMutation } from './mutations';
import { DeploymentsQuery } from './queries';
import { EXPO_BASE_DOMAIN } from './utils/logs';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { WorkerDeploymentFragment } from '../graphql/generated';
import Log from '../log';
import { promptAsync } from '../prompts';
import { memoize } from '../utils/expodash/memoize';
import { selectPaginatedAsync } from '../utils/relay';
export async function getSignedDeploymentUrlAsync(
graphqlClient: ExpoGraphqlClient,
exp: ExpoConfig,
deploymentVariables: {
options: {
appId: string;
deploymentIdentifier?: string | null;
/** Callback which is invoked when the project is going to setup the dev domain */
onSetupDevDomain?: () => any;
/** If the terminal is running in non interactive mode or not */
nonInteractive?: boolean;
}
): Promise<string> {
try {
return await DeploymentsMutation.createSignedDeploymentUrlAsync(
graphqlClient,
deploymentVariables
);
return await DeploymentsMutation.createSignedDeploymentUrlAsync(graphqlClient, {
appId: options.appId,
deploymentIdentifier: options.deploymentIdentifier,
});
} catch (error: any) {
const isMissingDevDomain = (error as GraphqlError)?.graphQLErrors?.some(e =>
['APP_NO_DEV_DOMAIN_NAME'].includes(e?.extensions?.errorCode as string)
@@ -27,40 +35,107 @@ export async function getSignedDeploymentUrlAsync(
if (!isMissingDevDomain) {
throw error;
}
if (options.nonInteractive) {
throw new Error(
'The project URL needs to be set up, but the terminal is running in non-interactive mode.'
);
}
const suggestedDevDomainName = await DeploymentsQuery.getSuggestedDevDomainByAppIdAsync(
graphqlClient,
{ appId: options.appId }
);
options.onSetupDevDomain?.();
await chooseDevDomainNameAsync({
graphqlClient,
appId: deploymentVariables.appId,
slug: exp.slug,
appId: options.appId,
initial: suggestedDevDomainName,
});
return await DeploymentsMutation.createSignedDeploymentUrlAsync(
graphqlClient,
deploymentVariables
);
return await DeploymentsMutation.createSignedDeploymentUrlAsync(graphqlClient, {
appId: options.appId,
deploymentIdentifier: options.deploymentIdentifier,
});
}
}
type PromptInstance = {
cursorOffset: number;
placeholder: boolean;
rendered: string;
initial: string;
get value(): string;
set value(input: string);
};
const DEV_DOMAIN_INVALID_START_END_CHARACTERS = /^[^a-z0-9]+|[^a-z0-9-]+$/;
const DEV_DOMAIN_INVALID_REPLACEMENT_HYPHEN = /[^a-z0-9-]+/;
const DEV_DOMAIN_INVALID_MULTIPLE_HYPHENS = /(-{2,})/;
/**
* Format a dev domain name to match whats allowed on the backend.
* This is equal to our `DEV_DOMAIN_NAME_REGEX`, but implemented as a filtering function
* to help users find a valid name while typing.
*/
function formatDevDomainName(name = ''): string {
return name
.toLowerCase()
.replace(DEV_DOMAIN_INVALID_REPLACEMENT_HYPHEN, '-')
.replace(DEV_DOMAIN_INVALID_START_END_CHARACTERS, '')
.replace(DEV_DOMAIN_INVALID_MULTIPLE_HYPHENS, '-')
.trim();
}
async function chooseDevDomainNameAsync({
graphqlClient,
appId,
slug,
initial,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
slug: string;
initial: string;
}): Promise<void> {
const validationMessage = 'The project does not have a dev domain name.';
const rootDomain = `.${EXPO_BASE_DOMAIN}.app`;
const memoizedFormatDevDomainName = memoize(formatDevDomainName);
const { name } = await promptAsync({
type: 'text',
name: 'name',
message: 'Choose a dev domain name for your project:',
validate: value => (value && value.length > 3 ? true : validationMessage),
initial: slug,
message: 'Choose a URL for your project:',
initial,
validate: (value: string) => {
if (!value) {
return 'You have to choose a URL for your project';
}
if (value.length < 3) {
return 'Project URLs must be at least 3 characters long';
}
if (value.endsWith('-')) {
return 'Project URLs cannot end with a hyphen (-)';
}
return true;
},
onState(this: PromptInstance, state: { value?: string }) {
const value = memoizedFormatDevDomainName(state.value);
if (value !== state.value) {
this.value = value;
}
},
onRender(this: PromptInstance, kleur) {
this.cursorOffset = -rootDomain.length - 1;
if (this.placeholder) {
this.rendered = kleur.dim(`${this.initial} ${rootDomain}`);
} else {
this.rendered = this.value + kleur.dim(` ${rootDomain}`);
}
},
});
if (!name) {
throw new Error('Prompt failed');
throw new Error('No project URL provided, aborting deployment.');
}
try {
@@ -70,7 +145,7 @@ async function chooseDevDomainNameAsync({
});
if (!success) {
throw new Error('Failed to assign dev domain name');
throw new Error('Failed to assign project URL');
}
} catch (error: any) {
const isChosenNameTaken = (error as GraphqlError)?.graphQLErrors?.some(e =>
@@ -78,8 +153,8 @@ async function chooseDevDomainNameAsync({
);
if (isChosenNameTaken) {
Log.error(`The entered dev domain name "${name}" is taken. Choose a different name.`);
await chooseDevDomainNameAsync({ graphqlClient, appId, slug });
Log.error(`The project URL "${name}" is already taken, choose a different name.`);
await chooseDevDomainNameAsync({ graphqlClient, appId, initial });
}
if (!isChosenNameTaken) {
@@ -87,3 +162,63 @@ async function chooseDevDomainNameAsync({
}
}
}
export async function assignWorkerDeploymentAliasAsync({
graphqlClient,
appId,
deploymentId,
aliasName,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
deploymentId: string;
aliasName: string;
}): ReturnType<typeof DeploymentsMutation.assignAliasAsync> {
return await DeploymentsMutation.assignAliasAsync(graphqlClient, {
appId,
deploymentId,
aliasName,
});
}
export async function assignWorkerDeploymentProductionAsync({
graphqlClient,
appId,
deploymentId,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
deploymentId: string;
}): ReturnType<typeof DeploymentsMutation.assignAliasAsync> {
return await DeploymentsMutation.assignAliasAsync(graphqlClient, {
appId,
deploymentId,
aliasName: null, // this will assign the deployment as production
});
}
export async function selectWorkerDeploymentOnAppAsync({
graphqlClient,
appId,
selectTitle,
pageSize,
}: {
graphqlClient: ExpoGraphqlClient;
appId: string;
selectTitle?: string;
pageSize?: number;
}): ReturnType<typeof selectPaginatedAsync<WorkerDeploymentFragment>> {
return await selectPaginatedAsync({
pageSize: pageSize ?? 25,
printedType: selectTitle ?? 'worker deployment',
queryAsync: async queryParams =>
await DeploymentsQuery.getAllDeploymentsPaginatedAsync(graphqlClient, {
...queryParams,
appId,
}),
getTitleAsync: async (deployment: WorkerDeploymentFragment) =>
chalk`${deployment.deploymentIdentifier}{dim - created at: ${new Date(
deployment.createdAt
).toLocaleString()}}`,
});
}
@@ -0,0 +1,11 @@
import gql from 'graphql-tag';
export const WorkerDeploymentFragmentNode = gql`
fragment WorkerDeploymentFragment on WorkerDeployment {
id
url
deploymentIdentifier
deploymentDomain
createdAt
}
`;
@@ -0,0 +1,9 @@
import gql from 'graphql-tag';
export const WorkerDeploymentAliasFragmentNode = gql`
fragment WorkerDeploymentAliasFragment on WorkerDeploymentAlias {
id
aliasName
url
}
`;
+45
View File
@@ -1,9 +1,14 @@
import assert from 'assert';
import { print } from 'graphql';
import gql from 'graphql-tag';
import { WorkerDeploymentFragmentNode } from './fragments/WorkerDeployment';
import { WorkerDeploymentAliasFragmentNode } from './fragments/WorkerDeploymentAlias';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../graphql/client';
import {
AssignAliasMutation,
AssignAliasMutationVariables,
AssignDevDomainNameMutation,
AssignDevDomainNameMutationVariables,
CreateDeploymentUrlMutation,
@@ -68,4 +73,44 @@ export const DeploymentsMutation = {
return data.devDomainName.assignDevDomainName.name === devDomainNameVariables.name;
},
async assignAliasAsync(
graphqlClient: ExpoGraphqlClient,
aliasVariables: { appId: string; deploymentId: string; aliasName: string | null }
): Promise<AssignAliasMutation['deployments']['assignAlias']> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<AssignAliasMutation, AssignAliasMutationVariables>(
gql`
mutation AssignAlias(
$appId: ID!
$deploymentId: ID!
$aliasName: WorkerDeploymentIdentifier
) {
deployments {
assignAlias(
appId: $appId
deploymentIdentifier: $deploymentId
aliasName: $aliasName
) {
id
...WorkerDeploymentAliasFragment
workerDeployment {
id
...WorkerDeploymentFragment
}
}
}
}
${print(WorkerDeploymentFragmentNode)}
${print(WorkerDeploymentAliasFragmentNode)}
`,
aliasVariables
)
.toPromise()
);
return data.deployments.assignAlias;
},
};
+89
View File
@@ -0,0 +1,89 @@
import { print } from 'graphql';
import gql from 'graphql-tag';
import { WorkerDeploymentFragmentNode } from './fragments/WorkerDeployment';
import type { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../graphql/client';
import {
type PaginatedWorkerDeploymentsQuery,
type PaginatedWorkerDeploymentsQueryVariables,
SuggestedDevDomainNameQuery,
SuggestedDevDomainNameQueryVariables,
type WorkerDeploymentFragment,
} from '../graphql/generated';
import type { Connection } from '../utils/relay';
export const DeploymentsQuery = {
async getAllDeploymentsPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
{ appId, first, after, last, before }: PaginatedWorkerDeploymentsQueryVariables
): Promise<Connection<WorkerDeploymentFragment>> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<PaginatedWorkerDeploymentsQuery, PaginatedWorkerDeploymentsQueryVariables>(
gql`
query PaginatedWorkerDeployments(
$appId: String!
$first: Int
$after: String
$last: Int
$before: String
) {
app {
byId(appId: $appId) {
id
workerDeployments(first: $first, after: $after, last: $last, before: $before) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
id
...WorkerDeploymentFragment
}
}
}
}
}
}
${print(WorkerDeploymentFragmentNode)}
`,
{ appId, first, after, last, before },
{ additionalTypenames: ['WorkerDeployment'] }
)
.toPromise()
);
return data.app.byId.workerDeployments;
},
async getSuggestedDevDomainByAppIdAsync(
graphqlClient: ExpoGraphqlClient,
{ appId }: SuggestedDevDomainNameQueryVariables
): Promise<string> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<SuggestedDevDomainNameQuery, SuggestedDevDomainNameQueryVariables>(
gql`
query SuggestedDevDomainName($appId: String!) {
app {
byId(appId: $appId) {
id
suggestedDevDomainName
}
}
}
`,
{ appId },
{ additionalTypenames: ['App'] }
)
.toPromise()
);
return data.app.byId.suggestedDevDomainName;
},
};
+82
View File
@@ -0,0 +1,82 @@
import chalk from 'chalk';
import type {
WorkerDeploymentAliasFragment,
WorkerDeploymentFragment,
} from '../../graphql/generated';
import formatFields, { type FormatFieldsItem } from '../../utils/formatFields';
export const EXPO_BASE_DOMAIN = process.env.EXPO_STAGING ? 'staging.expo' : 'expo';
export function getDeploymentUrlFromFullName(deploymentFullName: string): string {
return `https://${deploymentFullName}.${EXPO_BASE_DOMAIN}.app`;
}
export function getDashboardUrl(projectId: string): string {
return `https://${EXPO_BASE_DOMAIN}.dev/projects/${projectId}/hosting/deployments`;
}
type WorkerDeploymentData = {
/** Used to generate the dashboard URL to `expo.dev` */
projectId: string;
/** The actual deployment information */
deployment: Pick<WorkerDeploymentFragment, 'deploymentIdentifier' | 'url'>;
/** All modified aliases of the deployment, if any */
aliases?: WorkerDeploymentAliasFragment[];
/** The production promoting alias of the deployment, if any */
production?: WorkerDeploymentAliasFragment | null;
};
export function formatWorkerDeploymentTable(data: WorkerDeploymentData): string {
const fields: FormatFieldsItem[] = [
{ label: 'Dashboard', value: getDashboardUrl(data.projectId) },
{ label: 'Deployment URL', value: data.deployment.url },
];
if (data.aliases?.length) {
fields.push({ label: 'Alias URL', value: data.aliases[0].url });
}
if (data.production) {
fields.push({ label: 'Production URL', value: data.production.url });
}
const lastUrlField = fields[fields.length - 1];
lastUrlField.value = chalk.cyan(lastUrlField.value);
return formatFields(fields);
}
type WorkerDeploymentOutput = {
/** The absolute URL to the dashboard on `expo.dev` */
dashboardUrl: string;
/** The deployment information */
deployment: {
identifier: string;
url: string;
aliases?: { id: string; name: string; url: string }[];
production?: { id: string; url: string };
};
};
export function formatWorkerDeploymentJson(data: WorkerDeploymentData): WorkerDeploymentOutput {
return {
dashboardUrl: getDashboardUrl(data.projectId),
deployment: {
identifier: data.deployment.deploymentIdentifier,
url: data.deployment.url,
aliases: !data.aliases?.length
? undefined
: data.aliases.map(alias => ({
id: alias.id,
name: alias.aliasName,
url: alias.url,
})),
production: !data.production
? undefined
: {
id: data.production.id,
url: data.production.url,
},
},
};
}
Generated
+84 -30
View File
@@ -1477,6 +1477,17 @@
semver "^7.6.2"
zod "^3.23.8"
"@expo/env@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@expo/env/-/env-0.3.0.tgz#a66064e5656e0e48197525f47f3398034fdf579e"
integrity sha512-OtB9XVHWaXidLbHvrVDeeXa09yvTl3+IQN884sO6PhIi2/StXfgSH/9zC7IvzrDB8kW3EBJ1PPLuCUJ2hxAT7Q==
dependencies:
chalk "^4.0.0"
debug "^4.3.4"
dotenv "~16.4.5"
dotenv-expand "~11.0.6"
getenv "^1.0.0"
"@expo/fingerprint@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@expo/fingerprint/-/fingerprint-0.6.0.tgz#77366934673d4ecea37284109b4dd67f9e6a7487"
@@ -4876,10 +4887,10 @@ bl@^4.0.3, bl@^4.1.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
[email protected].2:
version "1.20.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
[email protected].3:
version "1.20.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
dependencies:
bytes "3.1.2"
content-type "~1.0.5"
@@ -4889,7 +4900,7 @@ [email protected]:
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.11.0"
qs "6.13.0"
raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
@@ -6188,6 +6199,13 @@ dotenv-expand@~10.0.0:
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37"
integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==
dotenv-expand@~11.0.6:
version "11.0.6"
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-11.0.6.tgz#f2c840fd924d7c77a94eff98f153331d876882d3"
integrity sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==
dependencies:
dotenv "^16.4.4"
[email protected], dotenv@~16.3.1:
version "16.3.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
@@ -6198,10 +6216,15 @@ dotenv@^16.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d"
integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==
dotenv@^16.4.4, dotenv@~16.4.5:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
dset@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
version "3.1.4"
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.4.tgz#f8eaf5f023f068a036d08cd07dc9ffb7d0065248"
integrity sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==
dtrace-provider@~0.8:
version "0.8.8"
@@ -6274,6 +6297,11 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
encodeurl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
encoding@^0.1.12, encoding@^0.1.13:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
@@ -6995,37 +7023,37 @@ expect@^29.7.0:
jest-message-util "^29.7.0"
jest-util "^29.7.0"
express@4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
express@4.20.0:
version "4.20.0"
resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48"
integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.2"
body-parser "1.20.3"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~1.0.2"
encodeurl "~2.0.0"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
http-errors "2.0.0"
merge-descriptors "1.0.1"
merge-descriptors "1.0.3"
methods "~1.1.2"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
path-to-regexp "0.1.10"
proxy-addr "~2.0.7"
qs "6.11.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
send "0.18.0"
serve-static "1.15.0"
send "0.19.0"
serve-static "1.16.0"
setprototypeof "1.2.0"
statuses "2.0.1"
type-is "~1.6.18"
@@ -10350,10 +10378,10 @@ meow@^8.1.2:
type-fest "^0.18.0"
yargs-parser "^20.2.3"
[email protected].1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
[email protected].3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
merge-stream@^2.0.0:
version "2.0.0"
@@ -11785,10 +11813,10 @@ path-scurry@^1.11.1:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
[email protected].7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
[email protected].10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
path-type@^3.0.0:
version "3.0.0"
@@ -12096,6 +12124,13 @@ [email protected]:
dependencies:
side-channel "^1.0.4"
[email protected]:
version "6.13.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
dependencies:
side-channel "^1.0.6"
[email protected]:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@@ -12686,6 +12721,25 @@ [email protected]:
range-parser "~1.2.1"
statuses "2.0.1"
[email protected]:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
dependencies:
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "2.0.0"
mime "1.6.0"
ms "2.1.3"
on-finished "2.4.1"
range-parser "~1.2.1"
statuses "2.0.1"
sentence-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f"
@@ -12695,10 +12749,10 @@ sentence-case@^3.0.4:
tslib "^2.0.3"
upper-case-first "^2.0.2"
[email protected]5.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
[email protected]6.0:
version "1.16.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92"
integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"