Compare commits

..
Author SHA1 Message Date
Quinlan Jung 0b995e0bed update CHANGELOG.md 2023-06-30 23:28:27 +00:00
Quinlan Jung 8f39b303c9 [eas-cli] bump config dependencies 2023-06-30 16:16:00 -07:00
c199173704 [eas-cli] Added alias -m for --message in eas update (#1904)
* added alias -m for --message

* align with the other messages

* updated README

* moving change in update/republish to a seperate PR

* removed README comment

* update CHANGELOG.md

---------

Co-authored-by: Steven Pu <[email protected]>
Co-authored-by: Steven Pu <[email protected]>
2023-06-28 11:36:18 -07:00
800098b958 [eas-cli] Added alias -m for --message in update/republish (#1905)
* added alias in republish

* reverted change in README

* update CHANGELOG.md

---------

Co-authored-by: Steven Pu <[email protected]>
Co-authored-by: Steven Pu <[email protected]>
2023-06-28 11:16:07 -07:00
Keith Kurak 146468914f Show build profile on eas build:run (#1901)
* [eas-cli] Add build profile to build:run list items

* say "simulator" or "emulator" in warning b/c we know which one

* update CHANGELOG.md
2023-06-27 08:40:57 -04:00
Szymon Dziedzic 0e48417983 [eas-cli] print better error message when uploading the project archive tarball fails (#1897)
* [eas-cli] print better error message when uplaoding tarball failed

* use better error class

* update CHANGELOG.md
2023-06-23 11:48:08 +02:00
Wojciech Kozyra cf61f585e6 Update CODEOWNERS (#1896) 2023-06-22 13:52:23 +02:00
Quinlan Jung cc700ae263 [eas-cli] better runtime output (#1894)
* [eas-cli] better runtime output

* update CHANGELOG.md
2023-06-21 12:47:33 -07:00
Expo CI 4e94c60c7f update CHANGELOG.md 2023-06-20 09:24:16 +00:00
Szymon Dziedzic 37f8e117e1 v3.14.0 2023-06-20 11:00:45 +02:00
Szymon Dziedzic 46095d2da4 upgrade eas-cli-local-build-plugin to 1.0.24 2023-06-20 11:00:20 +02:00
Szymon Dziedzic 6c01856617 [ENG-7183][eas-cli] validate that expo-updates are in project dependencies when somebody tries to run a build with channel set (#1885)
* [eas-cli] validate that `expo-updates` are in project dependencies when somebody tries to run a build with channel set

* apply suggested changes

* remove unnecessary change

* fix warning

* improve validation logic

* improve insatlled message

* warn when expo-updates are in dev dependencies for update command

* impreve warn messsages

* improve warning messages

* one more warn message improvement

* update CHANGELOG.md
2023-06-20 10:52:21 +02:00
Wojciech Kozyra f8cd50e0ed [eas-cli] Add minimal validation for app config returned by @expo/config (#1893)
* [eas-cli] Add minimal validation for app config returned by @expo/config

* update CHANGELOG.md
2023-06-20 10:41:52 +02:00
lzkb fd0a129a4f [eas-cli] change sso flag display (#1890) 2023-06-19 13:08:27 -07:00
Quinlan Jung c44e07bfeb [eas-cli] update:configure less verbose output (#1888)
* [eas-cli] less verbose output

* update CHANGELOG.md

* pr feedback
2023-06-19 11:12:37 -07:00
Piotr Szeremeta 951583e6ea [eas-cli][ENG-8763] Select default android keystore (#1889)
* [eas-cli][ENG-8763] Select default android keystore

- Add option to change default keystore from CLI (previously available only from dashboard)
- Streamline setting up new keystore

Instead of overwriting existing keystore, new one is created every time. Also, option to immediately set it as default is added, since it is also easier to change it from CLI.

* update CHANGELOG.md
2023-06-19 16:01:14 +02:00
Quinlan Jung 3f9247ca84 [eas-cli] build:configure add channels to eas.json if using eas updates (#1887)
* [eas-cli] configure build: amend eas.json for eas updates

* update CHANGELOG.md

* pr feedback
2023-06-17 16:14:23 -07:00
lzkb c38638e94e [eas-cli] Changes for SSO user type and SSO login. (#1875)
* [eas-cli] Changes for SSO user type and SSO login.
2023-06-16 10:44:13 -07:00
Brent VatneandQuinlan Jung 3b46466a9d [eas-cli] Initialize app.json if it does not exist, add expo key if missing (#1881)
Co-authored-by: Quinlan Jung <[email protected]>
2023-06-15 19:54:31 -07:00
Brent Vatne 806085cbf1 [eas-cli] Ensure that re-thrown error includes original stack (#1882) 2023-06-15 19:45:00 -07:00
Quinlan Jung 398b41cc81 [eas-cli] updates: error gracefully if no git repo (#1884)
* [eas-cli] updates: error gracefully if no git repo

* update CHANGELOG.md
2023-06-15 12:54:37 -07:00
Quinlan Jung d23a97238b [eas-cli] error gracefully if expo pkg not installed (#1883)
* [eas-cli] error gracefully if expo pkg not installed

* update CHANGELOG.md

* remove canadian language
2023-06-15 12:52:29 -07:00
Szymon Dziedzic 5b6f312ccb [eas-cli] bump @expo/steps version (#1886) 2023-06-15 15:20:54 +02:00
Aman MittalandWojciech Kozyra 2bcab0f2b4 [eas-cli] Update eas build:configure command to show link of eas.json when generated (#1878)
Co-authored-by: Wojciech Kozyra <[email protected]>
2023-06-14 16:15:53 +05:30
Stanisław Chmiela b90ce63067 Remove direct @types/bunyan dependency (#1880)
<!-- 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

Cleanup after https://github.com/expo/eas-build/pull/233.

# How

Upgraded `@expo/steps` package. It is the only `eas-build` package in here.

# Test Plan

It's a type-only change so CI success will be enough.
2023-06-13 17:05:37 +02:00
Szymon Dziedzic be02aced9d [eas-cli] update @expo/steps (#1876)
* [eas-cli] update `@expo/steps`

* update lockfile

* install @types/bunyan
2023-06-13 13:48:49 +02:00
Evan Bacon f788b081c6 feat(eas-cli): add new public entitlements from wwdc23 (#1870)
* feat(eas-cli): add new public entitlements from wwdc23

* update CHANGELOG.md
2023-06-07 13:29:01 -05:00
Expo CI 654f973d0e update CHANGELOG.md 2023-06-05 08:34:53 +00:00
53 changed files with 1617 additions and 483 deletions

No files matched your search

+34 -2
View File
@@ -8,13 +8,45 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Show build profile when selecting a build for eas build:run. ([#1901](https://github.com/expo/eas-cli/pull/1901) by [@keith-kurak](https://github.com/keith-kurak))
- Adds -m alias to --message in update/republish and removed README comment. ([#1905](https://github.com/expo/eas-cli/pull/1905) by [@pusongqi](https://github.com/pusongqi))
### 🐛 Bug fixes
### 🧹 Chores
- Better runtimeVersion output. ([#1894](https://github.com/expo/eas-cli/pull/1894) by [@quinlanj](https://github.com/quinlanj))
- Print better error message when uploading project archive tarball fails. ([#1897](https://github.com/expo/eas-cli/pull/1897) by [@szdziedzic](https://github.com/szdziedzic))
- Bump config dependencies. ([#1913](https://github.com/expo/eas-cli/pull/1913) by [@quinlanj](https://github.com/quinlanj))
## [3.14.0](https://github.com/expo/eas-cli/releases/tag/v3.14.0) - 2023-06-20
### 🎉 New features
- Added support for SSO users. ([#1875](https://github.com/expo/eas-cli/pull/1875) by [@lzkb](https://github.com/lzkb))
- Added new bundle identifier capabilities and entitlements from WWDC23. ([#1870](https://github.com/expo/eas-cli/pull/1870) by [@EvanBacon](https://github.com/EvanBacon))
- Selecting default keystore via CLI. ([#1889](https://github.com/expo/eas-cli/pull/1889) by [@khamilowicz](https://github.com/khamilowicz))
### 🧹 Chores
- Change sso flag display. ([#1890](https://github.com/expo/eas-cli/pull/1890) by [@lzkb](https://github.com/lzkb))
- Build:configure -- add channels to eas.json if using eas updates. ([#1887](https://github.com/expo/eas-cli/pull/1887) by [@quinlanj](https://github.com/quinlanj))
- Eas update: Error gracefully if no git repo. ([#1884](https://github.com/expo/eas-cli/pull/1884) by [@quinlanj](https://github.com/quinlanj))
- Error gracefully if expo pkg not installed. ([#1883](https://github.com/expo/eas-cli/pull/1883) by [@quinlanj](https://github.com/quinlanj))
- Update `eas build:configure` command to show the link of `eas.json` when generated. ([#1878](https://github.com/expo/eas-cli/pull/1878) by [@amandeepmittal](https://github.com/amandeepmittal))
- Create app.json or add the "expo" key if either are missing, before modifying or reading the file. ([#1881](https://github.com/expo/eas-cli/pull/1881) by [@brentvatne](https://github.com/brentvatne))
- Include the original stack in re-thrown errors thrown from EAS CLI commands. ([#1882](https://github.com/expo/eas-cli/pull/1882) by [@brentvatne](https://github.com/brentvatne))
- Make `update:configure` less verbose. ([#1888](https://github.com/expo/eas-cli/pull/1888) by [@quinlanj](https://github.com/quinlanj))
- Improve validation for values from app config. ([#1893](https://github.com/expo/eas-cli/pull/1893) by [@wkozyra95](https://github.com/wkozyra95))
- Improve `expo-updates` validation for builds with `channel` property set. ([#1885](https://github.com/expo/eas-cli/pull/1885) by [@szdziedzic](https://github.com/szdziedzic))
## [3.13.3](https://github.com/expo/eas-cli/releases/tag/v3.13.3) - 2023-06-05
### 🐛 Bug fixes
- Show original GraphQL error message in case of an unexpected error. ([#1862](https://github.com/expo/eas-cli/pull/1862) by [@dsokal](https://github.com/dsokal))
- Fix updates synchronization of native files to include strings.xml for bare projects. ([#1865](https://github.com/expo/eas-cli/pull/1865) by [@wschurman](https://github.com/wschurman))
### 🧹 Chores
## [3.13.2](https://github.com/expo/eas-cli/releases/tag/v3.13.2) - 2023-05-26
### 🧹 Chores
+6 -6
View File
@@ -1,10 +1,10 @@
* @szdziedzic @wkozyra95
* @szdziedzic @khamilowicz
packages/eas-cli/src/build @szdziedzic @wkozyra95
packages/eas-cli/src/commands/build @szdziedzic @wkozyra95
packages/eas-cli/src/build @szdziedzic @khamilowicz
packages/eas-cli/src/commands/build @szdziedzic @khamilowicz
packages/eas-cli/src/submit @szdziedzic
packages/eas-cli/src/commands/submit.ts @szdziedzic
packages/eas-cli/src/submit @szdziedzic @khamilowicz
packages/eas-cli/src/commands/submit.ts @szdziedzic @khamilowicz
packages/eas-cli/src/update @EvanBacon @byCedric @wschurman
packages/eas-cli/src/commands/update @EvanBacon @byCedric @wschurman
@@ -13,4 +13,4 @@ packages/eas-cli/schema @bycedric
packages/eas-cli/src/metadata @bycedric
packages/eas-cli/src/commands/metadata @bycedric
packages/eas-json @szdziedzic @wkozyra95
packages/eas-json @szdziedzic @khamilowicz
+1 -1
View File
@@ -1,6 +1,6 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "3.13.3",
"version": "3.14.0",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+121 -119
View File
@@ -55,68 +55,69 @@ eas --help COMMAND
# Commands
<!-- commands -->
* [`eas account:login`](#eas-accountlogin)
* [`eas account:logout`](#eas-accountlogout)
* [`eas account:view`](#eas-accountview)
* [`eas analytics [STATUS]`](#eas-analytics-status)
* [`eas autocomplete [SHELL]`](#eas-autocomplete-shell)
* [`eas branch:create [NAME]`](#eas-branchcreate-name)
* [`eas branch:delete [NAME]`](#eas-branchdelete-name)
* [`eas branch:list`](#eas-branchlist)
* [`eas branch:rename`](#eas-branchrename)
* [`eas branch:view [NAME]`](#eas-branchview-name)
* [`eas build`](#eas-build)
* [`eas build:cancel [BUILD_ID]`](#eas-buildcancel-build_id)
* [`eas build:configure`](#eas-buildconfigure)
* [`eas build:inspect`](#eas-buildinspect)
* [`eas build:list`](#eas-buildlist)
* [`eas build:resign`](#eas-buildresign)
* [`eas build:run`](#eas-buildrun)
* [`eas build:submit`](#eas-buildsubmit)
* [`eas build:version:get`](#eas-buildversionget)
* [`eas build:version:set`](#eas-buildversionset)
* [`eas build:version:sync`](#eas-buildversionsync)
* [`eas build:view [BUILD_ID]`](#eas-buildview-build_id)
* [`eas channel:create [NAME]`](#eas-channelcreate-name)
* [`eas channel:edit [NAME]`](#eas-channeledit-name)
* [`eas channel:list`](#eas-channellist)
* [`eas channel:rollout [CHANNEL]`](#eas-channelrollout-channel)
* [`eas channel:view [NAME]`](#eas-channelview-name)
* [`eas config`](#eas-config)
* [`eas credentials`](#eas-credentials)
* [`eas device:create`](#eas-devicecreate)
* [`eas device:delete`](#eas-devicedelete)
* [`eas device:list`](#eas-devicelist)
* [`eas device:rename`](#eas-devicerename)
* [`eas device:view [UDID]`](#eas-deviceview-udid)
* [`eas diagnostics`](#eas-diagnostics)
* [`eas help [COMMAND]`](#eas-help-command)
* [`eas init`](#eas-init)
* [`eas login`](#eas-login)
* [`eas logout`](#eas-logout)
* [`eas metadata:lint`](#eas-metadatalint)
* [`eas metadata:pull`](#eas-metadatapull)
* [`eas metadata:push`](#eas-metadatapush)
* [`eas open`](#eas-open)
* [`eas project:info`](#eas-projectinfo)
* [`eas project:init`](#eas-projectinit)
* [`eas secret:create`](#eas-secretcreate)
* [`eas secret:delete`](#eas-secretdelete)
* [`eas secret:list`](#eas-secretlist)
* [`eas secret:push`](#eas-secretpush)
* [`eas submit`](#eas-submit)
* [`eas update`](#eas-update)
* [`eas update:configure`](#eas-updateconfigure)
* [`eas update:delete GROUPID`](#eas-updatedelete-groupid)
* [`eas update:list`](#eas-updatelist)
* [`eas update:republish`](#eas-updaterepublish)
* [`eas update:view GROUPID`](#eas-updateview-groupid)
* [`eas webhook:create`](#eas-webhookcreate)
* [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
* [`eas webhook:list`](#eas-webhooklist)
* [`eas webhook:update`](#eas-webhookupdate)
* [`eas webhook:view ID`](#eas-webhookview-id)
* [`eas whoami`](#eas-whoami)
- [`eas account:login`](#eas-accountlogin)
- [`eas account:logout`](#eas-accountlogout)
- [`eas account:view`](#eas-accountview)
- [`eas analytics [STATUS]`](#eas-analytics-status)
- [`eas autocomplete [SHELL]`](#eas-autocomplete-shell)
- [`eas branch:create [NAME]`](#eas-branchcreate-name)
- [`eas branch:delete [NAME]`](#eas-branchdelete-name)
- [`eas branch:list`](#eas-branchlist)
- [`eas branch:rename`](#eas-branchrename)
- [`eas branch:view [NAME]`](#eas-branchview-name)
- [`eas build`](#eas-build)
- [`eas build:cancel [BUILD_ID]`](#eas-buildcancel-build_id)
- [`eas build:configure`](#eas-buildconfigure)
- [`eas build:inspect`](#eas-buildinspect)
- [`eas build:list`](#eas-buildlist)
- [`eas build:resign`](#eas-buildresign)
- [`eas build:run`](#eas-buildrun)
- [`eas build:submit`](#eas-buildsubmit)
- [`eas build:version:get`](#eas-buildversionget)
- [`eas build:version:set`](#eas-buildversionset)
- [`eas build:version:sync`](#eas-buildversionsync)
- [`eas build:view [BUILD_ID]`](#eas-buildview-build_id)
- [`eas channel:create [NAME]`](#eas-channelcreate-name)
- [`eas channel:edit [NAME]`](#eas-channeledit-name)
- [`eas channel:list`](#eas-channellist)
- [`eas channel:rollout [CHANNEL]`](#eas-channelrollout-channel)
- [`eas channel:view [NAME]`](#eas-channelview-name)
- [`eas config`](#eas-config)
- [`eas credentials`](#eas-credentials)
- [`eas device:create`](#eas-devicecreate)
- [`eas device:delete`](#eas-devicedelete)
- [`eas device:list`](#eas-devicelist)
- [`eas device:rename`](#eas-devicerename)
- [`eas device:view [UDID]`](#eas-deviceview-udid)
- [`eas diagnostics`](#eas-diagnostics)
- [`eas help [COMMAND]`](#eas-help-command)
- [`eas init`](#eas-init)
- [`eas login`](#eas-login)
- [`eas logout`](#eas-logout)
- [`eas metadata:lint`](#eas-metadatalint)
- [`eas metadata:pull`](#eas-metadatapull)
- [`eas metadata:push`](#eas-metadatapush)
- [`eas open`](#eas-open)
- [`eas project:info`](#eas-projectinfo)
- [`eas project:init`](#eas-projectinit)
- [`eas secret:create`](#eas-secretcreate)
- [`eas secret:delete`](#eas-secretdelete)
- [`eas secret:list`](#eas-secretlist)
- [`eas secret:push`](#eas-secretpush)
- [`eas submit`](#eas-submit)
- [`eas update`](#eas-update)
- [`eas update:configure`](#eas-updateconfigure)
- [`eas update:delete GROUPID`](#eas-updatedelete-groupid)
- [`eas update:list`](#eas-updatelist)
- [`eas update:republish`](#eas-updaterepublish)
- [`eas update:view GROUPID`](#eas-updateview-groupid)
- [`eas webhook:create`](#eas-webhookcreate)
- [`eas webhook:delete [ID]`](#eas-webhookdelete-id)
- [`eas webhook:list`](#eas-webhooklist)
- [`eas webhook:update`](#eas-webhookupdate)
- [`eas webhook:view ID`](#eas-webhookview-id)
- [`eas whoami`](#eas-whoami)
## `eas account:login`
@@ -133,7 +134,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -150,7 +151,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -167,7 +168,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -181,7 +182,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -231,7 +232,7 @@ DESCRIPTION
create a branch
```
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -252,7 +253,7 @@ DESCRIPTION
delete a branch
```
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -272,7 +273,7 @@ DESCRIPTION
list all branches
```
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -292,7 +293,7 @@ DESCRIPTION
rename a branch
```
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -315,7 +316,7 @@ DESCRIPTION
view a branch
```
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -345,7 +346,7 @@ DESCRIPTION
start a build
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -362,7 +363,7 @@ DESCRIPTION
cancel a build
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -379,7 +380,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:inspect`
@@ -414,7 +415,7 @@ DESCRIPTION
inspect the state of the project at specific build stages, useful for troubleshooting
```
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -452,7 +453,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -478,7 +479,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/resign.ts)_
_See code: [src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -502,7 +503,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/run.ts)_
_See code: [src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -551,7 +552,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/version/get.ts)_
_See code: [src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -570,7 +571,7 @@ DESCRIPTION
update version of an app
```
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/version/set.ts)_
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -589,7 +590,7 @@ DESCRIPTION
update a version in native code with a value stored on EAS servers
```
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/version/sync.ts)_
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -606,7 +607,7 @@ DESCRIPTION
view a build for your project
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -627,7 +628,7 @@ DESCRIPTION
create a channel
```
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -649,7 +650,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -669,7 +670,7 @@ DESCRIPTION
list all channels
```
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -693,7 +694,7 @@ DESCRIPTION
Roll a new branch out on a channel incrementally.
```
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/channel/rollout.ts)_
_See code: [src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -716,7 +717,7 @@ DESCRIPTION
view a channel
```
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -737,7 +738,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/config.ts)_
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -754,7 +755,7 @@ DESCRIPTION
manage credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/credentials.ts)_
## `eas device:create`
@@ -768,7 +769,7 @@ DESCRIPTION
register new Apple Devices to use for internal distribution
```
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -788,7 +789,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -809,7 +810,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -830,7 +831,7 @@ DESCRIPTION
rename a registered device
```
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/device/rename.ts)_
_See code: [src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -844,7 +845,7 @@ DESCRIPTION
view a device for your project
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -858,7 +859,7 @@ DESCRIPTION
display environment info
```
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -946,7 +947,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -963,7 +964,7 @@ DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -980,7 +981,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas open`
@@ -994,7 +995,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/open.ts)_
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1008,7 +1009,7 @@ DESCRIPTION
information about the current project
```
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/project/info.ts)_
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1030,7 +1031,7 @@ ALIASES
$ eas init
```
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/project/init.ts)_
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1053,7 +1054,7 @@ DESCRIPTION
create an environment secret on the current project or owner account
```
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1071,7 +1072,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1085,7 +1086,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1105,7 +1106,7 @@ DESCRIPTION
read environment secrets from env file and store on the server
```
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1135,7 +1136,7 @@ ALIASES
$ eas build:submit
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1156,7 +1157,7 @@ FLAGS
--group=<value> Update group to republish (deprecated, see republish command)
--input-dir=<value> [default: dist] Location of the bundle
--json Enable JSON output, non-JSON messages will be printed to stderr.
--message=<value> A short message describing the update
--message=<value> A short message describing the update
--non-interactive Run the command in non-interactive mode.
--private-key-path=<value> File containing the PEM-encoded private key corresponding to the certificate in
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
@@ -1168,7 +1169,7 @@ DESCRIPTION
publish an update group
```
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/index.ts)_
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1186,7 +1187,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1207,7 +1208,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1229,7 +1230,7 @@ DESCRIPTION
view the recent updates
```
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/list.ts)_
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1246,14 +1247,14 @@ FLAGS
--channel=<value> Channel name to select an update to republish from
--group=<value> Update group ID to republish
--json Enable JSON output, non-JSON messages will be printed to stderr.
--message=<value> Short message describing the republished update
--message=<value> Short message describing the republished update
--non-interactive Run the command in non-interactive mode.
DESCRIPTION
roll back to an existing update
```
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/republish.ts)_
_See code: [src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:view GROUPID`
@@ -1273,7 +1274,7 @@ DESCRIPTION
update group details
```
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/update/view.ts)_
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1294,7 +1295,7 @@ DESCRIPTION
create a webhook
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1314,7 +1315,7 @@ DESCRIPTION
delete a webhook
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1332,7 +1333,7 @@ DESCRIPTION
list webhooks
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1354,7 +1355,7 @@ DESCRIPTION
update a webhook
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1371,7 +1372,7 @@ DESCRIPTION
view a webhook
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v3.13.3/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v3.14.0/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
@@ -1387,4 +1388,5 @@ DESCRIPTION
ALIASES
$ eas whoami
```
<!-- commandsstop -->
+404 -142
View File
@@ -7252,6 +7252,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "filter",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "ChannelFilterInput",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "first",
"description": null,
@@ -9250,6 +9262,22 @@
"name": "AppInsights",
"description": null,
"fields": [
{
"name": "hasEventsFromExpoInsightsClientModule",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "totalUniqueUsers",
"description": null,
@@ -13469,6 +13497,277 @@
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "BackgroundJobReceipt",
"description": null,
"fields": [
{
"name": "account",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Account",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createdAt",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "DateTime",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errorCode",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errorMessage",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "resultId",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "resultType",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "BackgroundJobResultType",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "state",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "BackgroundJobState",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "tries",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updatedAt",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "DateTime",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "willRetry",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "BackgroundJobReceiptQuery",
"description": null,
"fields": [
{
"name": "byId",
"description": "Look up background job receipt by ID",
"args": [
{
"name": "id",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "BackgroundJobReceipt",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "BackgroundJobResultType",
"description": null,
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "GITHUB_BUILD",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "BackgroundJobState",
"description": null,
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "FAILURE",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "IN_PROGRESS",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "QUEUED",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "SUCCESS",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Billing",
@@ -17037,6 +17336,29 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "ChannelFilterInput",
"description": null,
"fields": null,
"inputFields": [
{
"name": "searchTerm",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Charge",
@@ -20686,7 +21008,7 @@
"fields": [
{
"name": "createGitHubBuild",
"description": "Create a GitHub build for an app",
"description": "Create a GitHub build for an app. Returns the ID of the background job receipt. Use BackgroundJobReceiptQuery to get the status of the job.",
"args": [
{
"name": "buildInput",
@@ -20709,8 +21031,8 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"kind": "OBJECT",
"name": "BackgroundJobReceipt",
"ofType": null
}
},
@@ -28679,6 +29001,22 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "backgroundJobReceipt",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "BackgroundJobReceiptQuery",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "buildJobs",
"description": null,
@@ -29314,8 +29652,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "apps",
@@ -29524,8 +29862,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "id",
@@ -29552,8 +29890,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "isExpoAdmin",
@@ -29592,8 +29930,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "notificationSubscriptions",
@@ -29730,8 +30068,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "username",
@@ -29784,30 +30122,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "githubUsername",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "industry",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "lastName",
"description": null,
@@ -29819,30 +30133,6 @@
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "location",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "twitterUsername",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
@@ -32955,6 +33245,22 @@
"name": "UpdateBranch",
"description": null,
"fields": [
{
"name": "app",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "App",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "appId",
"description": null,
@@ -33367,6 +33673,22 @@
"name": "UpdateChannel",
"description": null,
"fields": [
{
"name": "app",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "App",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "appId",
"description": null,
@@ -34413,8 +34735,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "apps",
@@ -34651,8 +34973,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "hasPendingUserInvitations",
@@ -34695,8 +35017,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "isExpoAdmin",
@@ -34728,7 +35050,7 @@
}
},
"isDeprecated": true,
"deprecationReason": "This field no longer exists"
"deprecationReason": "No longer supported"
},
{
"name": "isSecondFactorAuthenticationEnabled",
@@ -34767,8 +35089,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "notificationSubscriptions",
@@ -34953,8 +35275,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "username",
@@ -35140,8 +35462,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "apps",
@@ -35350,8 +35672,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "id",
@@ -35378,8 +35700,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "isExpoAdmin",
@@ -35418,8 +35740,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "notificationSubscriptions",
@@ -35556,8 +35878,8 @@
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "No longer supported"
},
{
"name": "username",
@@ -35681,18 +36003,6 @@
"description": null,
"fields": null,
"inputFields": [
{
"name": "appetizeCode",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "email",
"description": null,
@@ -35729,18 +36039,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "githubUsername",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": null,
@@ -35753,18 +36051,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "industry",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "lastName",
"description": null,
@@ -35777,18 +36063,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "location",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "profilePhoto",
"description": null,
@@ -35801,18 +36075,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "twitterUsername",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "username",
"description": null,
+7 -6
View File
@@ -1,18 +1,18 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "3.13.3",
"version": "3.14.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "1.2.0",
"@expo/apple-utils": "1.3.1",
"@expo/code-signing-certificates": "0.0.5",
"@expo/config": "7.0.3",
"@expo/config-plugins": "6.0.2",
"@expo/config-types": "47.0.0",
"@expo/config": "8.1.2",
"@expo/config-plugins": "7.2.3",
"@expo/config-types": "49.0.0",
"@expo/eas-build-job": "1.0.13",
"@expo/eas-json": "3.13.0",
"@expo/json-file": "8.2.37",
@@ -27,7 +27,7 @@
"@expo/results": "1.0.0",
"@expo/rudder-sdk-node": "1.1.1",
"@expo/spawn-async": "1.7.0",
"@expo/steps": "1.0.13",
"@expo/steps": "1.0.23",
"@expo/timeago.js": "1.0.0",
"@oclif/core": "1.23.2",
"@oclif/plugin-autocomplete": "1.3.10",
@@ -47,6 +47,7 @@
"fast-glob": "3.2.12",
"figures": "3.2.0",
"form-data": "4.0.0",
"freeport-async": "2.0.0",
"fs-extra": "10.1.0",
"getenv": "1.0.0",
"gradle-to-js": "2.0.1",
+12
View File
@@ -2,6 +2,7 @@ import { JSONValue } from '@expo/json-file';
import { ApiV2Error } from './ApiV2Error';
import fetch, { RequestError, RequestInit } from './fetch';
import { getFreePortAsync } from './utils/port';
interface RequestOptions {
body: JSONValue;
@@ -104,3 +105,14 @@ export function getEASUpdateURL(projectId: string): string {
return new URL(projectId, `https://u.expo.dev`).href;
}
}
export async function getSsoLocalServerPortAsync(): Promise<number> {
let startPort: number;
if (process.env.SSO_LOCAL_SERVER_PORT) {
startPort = Number(process.env.SSO_LOCAL_SERVER_PORT);
} else {
startPort = 19300;
}
const port = await getFreePortAsync(startPort);
return port;
}
+7
View File
@@ -42,6 +42,7 @@ import {
EasBuildFreeTierDisabledAndroidError,
EasBuildFreeTierDisabledError,
EasBuildFreeTierDisabledIOSError,
EasBuildProjectArchiveUploadError,
EasBuildResourceClassNotAvailableInFreeTierError,
EasBuildTooManyPendingBuildsError,
RequestValidationError,
@@ -269,6 +270,12 @@ async function uploadProjectAsync<TPlatform extends Platform>(
properties: ctx.analyticsEventProperties,
}
);
} catch (err: any) {
let errMessage = 'Failed to upload the project tarball to EAS Build';
if (err.message) {
errMessage += `\n\nReason: ${err.message}`;
}
throw new EasBuildProjectArchiveUploadError(errMessage);
} finally {
if (projectTarballPath) {
await fs.remove(projectTarballPath);
+11 -3
View File
@@ -3,7 +3,7 @@ import { EasJson, EasJsonAccessor } from '@expo/eas-json';
import chalk from 'chalk';
import fs from 'fs-extra';
import Log from '../log';
import Log, { learnMore } from '../log';
import { resolveWorkflowAsync } from '../project/workflow';
import { easCliVersion } from '../utils/easCli';
import { getVcsClient } from '../vcs';
@@ -14,6 +14,10 @@ interface ConfigureParams {
nonInteractive: boolean;
}
export async function easJsonExistsAsync(projectDir: string): Promise<boolean> {
return await fs.pathExists(EasJsonAccessor.formatEasJsonPath(projectDir));
}
/**
* Creates eas.json if it does not exist.
*
@@ -24,7 +28,7 @@ interface ConfigureParams {
export async function ensureProjectConfiguredAsync(
configureParams: ConfigureParams
): Promise<boolean> {
if (await fs.pathExists(EasJsonAccessor.formatEasJsonPath(configureParams.projectDir))) {
if (await easJsonExistsAsync(configureParams.projectDir)) {
return false;
}
@@ -102,5 +106,9 @@ async function createEasJsonAsync(projectDir: string): Promise<void> {
await fs.writeFile(easJsonPath, `${JSON.stringify(easJson, null, 2)}\n`);
await getVcsClient().trackFileAsync(easJsonPath);
Log.withTick(`Generated ${chalk.bold('eas.json')}`);
Log.withTick(
`Generated ${chalk.bold('eas.json')}. ${learnMore(
'https://docs.expo.dev/build-reference/eas-json/'
)}`
);
}
+2
View File
@@ -15,3 +15,5 @@ export class RequestValidationError extends EasCommandError {}
export class EasBuildDownForMaintenanceError extends EasCommandError {}
export class EasBuildTooManyPendingBuildsError extends EasCommandError {}
export class EasBuildProjectArchiveUploadError extends EasCommandError {}
+1 -1
View File
@@ -6,7 +6,7 @@ import semver from 'semver';
import { ora } from '../ora';
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
const PLUGIN_PACKAGE_VERSION = '1.0.18';
const PLUGIN_PACKAGE_VERSION = '1.0.24';
export enum LocalBuildMode {
/**
+1
View File
@@ -132,6 +132,7 @@ function createBuildToPartialChoiceMaker(
name: build.platform === AppPlatform.Ios ? 'Build number' : 'Version code',
value: build.appBuildVersion ? chalk.bold(build.appBuildVersion) : null,
},
{ name: 'Profile', value: build.buildProfile ? chalk.bold(build.buildProfile) : null },
];
const filteredDescriptionArray: string[] = descriptionItems
@@ -37,7 +37,12 @@ import {
} from '../project/customBuildConfig';
import { checkExpoSdkIsSupportedAsync } from '../project/expoSdk';
import { validateMetroConfigForManagedWorkflowAsync } from '../project/metroConfig';
import { validateAppVersionRuntimePolicySupportAsync } from '../project/projectUtils';
import {
installExpoUpdatesAsync,
isExpoUpdatesInstalledAsDevDependency,
isExpoUpdatesInstalledOrAvailable,
validateAppVersionRuntimePolicySupportAsync,
} from '../project/projectUtils';
import {
validateAppConfigForRemoteVersionSource,
validateBuildProfileVersionSettings,
@@ -306,6 +311,14 @@ async function prepareAndStartBuildAsync({
buildCtx.projectId,
flags.nonInteractive
);
if (buildProfile.profile.channel) {
await validateExpoUpdatesInstalledAsProjectDependencyAsync({
projectDir,
sdkVersion: buildCtx.exp.sdkVersion,
nonInteractive: flags.nonInteractive,
buildProfile,
});
}
await validateAppVersionRuntimePolicySupportAsync(buildCtx.projectDir, buildCtx.exp);
if (easJsonCliConfig?.appVersionSource === AppVersionSource.REMOTE) {
@@ -425,3 +438,40 @@ async function maybeDownloadAndRunSimulatorBuildsAsync(
}
}
}
async function validateExpoUpdatesInstalledAsProjectDependencyAsync({
projectDir,
buildProfile,
nonInteractive,
sdkVersion,
}: {
projectDir: string;
buildProfile: ProfileData<'build'>;
nonInteractive: boolean;
sdkVersion?: string;
}): Promise<void> {
if (isExpoUpdatesInstalledOrAvailable(projectDir, sdkVersion)) {
return;
}
if (isExpoUpdatesInstalledAsDevDependency(projectDir)) {
Log.warn(
`The build profile "${buildProfile.profileName}" uses the channel "${buildProfile.profile.channel}", but you've added "expo-updates" as a dev dependency. To make channels work for your builds, move "expo-updates" from dev dependencies to the main dependencies in your project.`
);
} else if (nonInteractive) {
Log.warn(
`The build profile "${buildProfile.profileName}" has specified the channel "${buildProfile.profile.channel}", but the "expo-updates" package hasn't been installed. To use channels for your builds, install the "expo-updates" package by running "npx expo install expo-updates".`
);
} else {
Log.warn(
`The build profile "${buildProfile.profileName}" specifies the channel "${buildProfile.profile.channel}", but the "expo-updates" package is missing. To use channels in your builds, install the "expo-updates" package.`
);
const installExpoUpdates = await confirmAsync({
message: `Would you like to install the "expo-updates" package?`,
});
if (installExpoUpdates) {
await installExpoUpdatesAsync(projectDir, { silent: false });
Log.withTick('Installed expo-updates');
}
}
}
@@ -203,6 +203,8 @@ export default abstract class EasCommand extends Command {
Log.error(err.message);
}
Log.debug(err);
throw new Error(baseMessage);
const sanitizedError = new Error(baseMessage);
sanitizedError.stack = err.stack;
throw sanitizedError;
}
}
@@ -1,4 +1,4 @@
import { getProjectConfigDescription, modifyConfigAsync } from '@expo/config';
import { getProjectConfigDescription } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Env } from '@expo/eas-build-job';
import chalk from 'chalk';
@@ -6,7 +6,7 @@ import chalk from 'chalk';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import Log, { learnMore } from '../../../log';
import { ora } from '../../../ora';
import { getPrivateExpoConfig } from '../../../project/expoConfig';
import { createOrModifyExpoConfigAsync, getPrivateExpoConfig } from '../../../project/expoConfig';
import { fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync } from '../../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync';
import { toAppPrivacy } from '../../../project/projectUtils';
import SessionManager from '../../../user/SessionManager';
@@ -25,7 +25,7 @@ export async function saveProjectIdToAppConfigAsync(
options: { env?: Env } = {}
): Promise<void> {
const exp = getPrivateExpoConfig(projectDir, options);
const result = await modifyConfigAsync(
const result = await createOrModifyExpoConfigAsync(
projectDir,
{
extra: { ...exp.extra, eas: { ...exp.extra?.eas, projectId } },
@@ -160,12 +160,12 @@ export async function getProjectIdAsync(
switch (user.__typename) {
case 'User':
return user.username;
case 'SSOUser':
return user.username;
case 'Robot':
throw new Error(
'The "owner" manifest property is required when using robot users. See: https://docs.expo.dev/versions/latest/config/app/#owner'
);
case 'SSOUser':
throw new Error('SSO users are not supported yet.');
}
};
+17 -1
View File
@@ -1,3 +1,5 @@
import { Flags } from '@oclif/core';
import EasCommand from '../../commandUtils/EasCommand';
import Log from '../../log';
@@ -5,13 +7,27 @@ export default class AccountLogin extends EasCommand {
static override description = 'log in with your Expo account';
static override aliases = ['login'];
static override flags = {
// can pass either --sso or -s
sso: Flags.boolean({
description: 'Login with SSO',
char: 's',
default: false,
hidden: true,
}),
};
static override contextDefinition = {
...this.ContextOptions.SessionManagment,
};
async runAsync(): Promise<void> {
const {
flags: { sso },
} = await this.parse(AccountLogin);
const { sessionManager } = await this.getContextAsync(AccountLogin, { nonInteractive: false });
await sessionManager.showLoginPromptAsync();
await sessionManager.showLoginPromptAsync({ sso });
Log.log('Logged in');
}
}
@@ -7,10 +7,11 @@ import { ensureProjectConfiguredAsync } from '../../build/configure';
import EasCommand from '../../commandUtils/EasCommand';
import Log, { learnMore } from '../../log';
import { RequestedPlatform } from '../../platform';
import { isExpoUpdatesInstalled } from '../../project/projectUtils';
import { isExpoUpdatesInstalled, isUsingEASUpdate } from '../../project/projectUtils';
import { resolveWorkflowAsync } from '../../project/workflow';
import { promptAsync } from '../../prompts';
import { syncUpdatesConfigurationAsync as syncAndroidUpdatesConfigurationAsync } from '../../update/android/UpdatesModule';
import { ensureEASUpdateIsConfiguredInEasJsonAsync } from '../../update/configure';
import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } from '../../update/ios/UpdatesModule';
import { getVcsClient } from '../../vcs';
@@ -57,10 +58,13 @@ export default class BuildConfigure extends EasCommand {
// ensure eas.json exists
Log.newLine();
await ensureProjectConfiguredAsync({
const didCreateEasJson = await ensureProjectConfiguredAsync({
projectDir,
nonInteractive: false,
});
if (didCreateEasJson && isUsingEASUpdate(exp, projectId)) {
await ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir);
}
// configure expo-updates
if (expoUpdatesIsInstalled) {
+3 -2
View File
@@ -210,8 +210,9 @@ async function maybeGetBuildAsync(
},
paginatedQueryOptions,
selectPromptDisabledFunction: build => !isRunnableOnSimulatorOrEmulator(build),
selectPromptWarningMessage:
'Artifacts for this build have expired and are no longer available, or this is not a simulator/emulator build.',
selectPromptWarningMessage: `Artifacts for this build have expired and are no longer available, or this is not ${
flags.selectedPlatform === AppPlatform.Ios ? 'a simulator' : 'an emulator'
} build.`,
});
return validateChosenBuild(build, flags.selectedPlatform);
} else if (flags.runArchiveFlags.latest) {
@@ -1,4 +1,4 @@
import { AppJSONConfig, PackageJSONConfig, getConfig, modifyConfigAsync } from '@expo/config';
import { AppJSONConfig, PackageJSONConfig, getConfig } from '@expo/config';
import chalk from 'chalk';
import { vol } from 'memfs';
import { instance, mock } from 'ts-mockito';
@@ -12,12 +12,17 @@ import FeatureGating from '../../../commandUtils/gating/FeatureGating';
import { jester, jester2 } from '../../../credentials/__tests__/fixtures-constants';
import { AppMutation } from '../../../graphql/mutations/AppMutation';
import { AppQuery } from '../../../graphql/queries/AppQuery';
import { createOrModifyExpoConfigAsync } from '../../../project/expoConfig';
import { findProjectIdByAccountNameAndSlugNullableAsync } from '../../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync';
import { confirmAsync, promptAsync } from '../../../prompts';
import ProjectInit from '../init';
jest.mock('fs');
jest.mock('@expo/config');
jest.mock('../../../project/expoConfig', () => ({
...jest.requireActual('../../../project/expoConfig'),
createOrModifyExpoConfigAsync: jest.fn(),
}));
jest.mock('../../../prompts');
jest.mock('../../../user/actions');
jest.mock('../../../graphql/mutations/AppMutation');
@@ -143,13 +148,16 @@ describe(ProjectInit.name, () => {
});
describe('force', () => {
it('does not prompt to overwrite when different', async () => {
beforeEach(() => {
jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
id: '1234',
slug: 'testing-123',
fullName: '@jester/testing-123',
ownerAccount: jester.accounts[0],
});
});
it('does not prompt to overwrite when different', async () => {
await new ProjectInit(['--id', '12345', '--force'], {
root: '/test-project',
} as any).run();
@@ -183,7 +191,7 @@ describe(ProjectInit.name, () => {
});
await new ProjectInit(['--id', '1234'], commandOptions).run();
expect(modifyConfigAsync).not.toHaveBeenCalled();
expect(createOrModifyExpoConfigAsync).not.toHaveBeenCalled();
});
it('prompts to configure if not consistent', async () => {
@@ -195,14 +203,20 @@ describe(ProjectInit.name, () => {
});
jest.mocked(confirmAsync).mockResolvedValue(true);
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await new ProjectInit(['--id', '1234'], commandOptions).run();
expect(confirmAsync).toHaveBeenCalled();
expect(modifyConfigAsync).toHaveBeenCalledTimes(2);
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { owner: 'jester2' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { slug: 'testing-124' });
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledTimes(2);
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
owner: 'jester2',
});
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
slug: 'testing-124',
});
});
it('overrides if force flag is present and it is not consistent', async () => {
@@ -213,14 +227,20 @@ describe(ProjectInit.name, () => {
ownerAccount: jester2.accounts[0],
});
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await new ProjectInit(['--id', '1234', '--force'], commandOptions).run();
expect(confirmAsync).not.toHaveBeenCalled();
expect(modifyConfigAsync).toHaveBeenCalledTimes(2);
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { owner: 'jester2' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { slug: 'testing-124' });
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledTimes(2);
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
owner: 'jester2',
});
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
slug: 'testing-124',
});
});
it('throws if non-interactive is present and it is not consistent', async () => {
@@ -231,7 +251,9 @@ describe(ProjectInit.name, () => {
ownerAccount: jester2.accounts[0],
});
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await expect(
new ProjectInit(['--id', '1234', '--non-interactive'], commandOptions).run()
@@ -240,7 +262,7 @@ describe(ProjectInit.name, () => {
);
expect(confirmAsync).not.toHaveBeenCalled();
expect(modifyConfigAsync).not.toHaveBeenCalled();
expect(createOrModifyExpoConfigAsync).not.toHaveBeenCalled();
});
});
});
@@ -271,7 +293,7 @@ describe(ProjectInit.name, () => {
});
await new ProjectInit(['--id', '1234'], commandOptions).run();
expect(modifyConfigAsync).not.toHaveBeenCalled();
expect(createOrModifyExpoConfigAsync).not.toHaveBeenCalled();
});
it('prompts to configure if not consistent', async () => {
@@ -285,14 +307,20 @@ describe(ProjectInit.name, () => {
});
jest.mocked(confirmAsync).mockResolvedValue(true);
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await new ProjectInit(['--id', '1234'], commandOptions).run();
expect(confirmAsync).toHaveBeenCalled();
expect(modifyConfigAsync).toHaveBeenCalledTimes(2);
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { owner: 'jester2' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { slug: 'testing-124' });
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledTimes(2);
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
owner: 'jester2',
});
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
slug: 'testing-124',
});
});
it('overrides if force flag is present and it is not consistent', async () => {
@@ -305,14 +333,20 @@ describe(ProjectInit.name, () => {
ownerAccount: jester2.accounts[0],
});
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await new ProjectInit(['--id', '1234', '--force'], commandOptions).run();
expect(confirmAsync).not.toHaveBeenCalled();
expect(modifyConfigAsync).toHaveBeenCalledTimes(2);
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { owner: 'jester2' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { slug: 'testing-124' });
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledTimes(2);
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
owner: 'jester2',
});
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
slug: 'testing-124',
});
});
it('throws if non-interactive is present and it is not consistent', async () => {
@@ -325,7 +359,9 @@ describe(ProjectInit.name, () => {
ownerAccount: jester2.accounts[0],
});
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await expect(
new ProjectInit(['--id', '1234', '--non-interactive'], commandOptions).run()
@@ -334,7 +370,7 @@ describe(ProjectInit.name, () => {
);
expect(confirmAsync).not.toHaveBeenCalled();
expect(modifyConfigAsync).not.toHaveBeenCalled();
expect(createOrModifyExpoConfigAsync).not.toHaveBeenCalled();
});
});
});
@@ -367,14 +403,20 @@ describe(ProjectInit.name, () => {
});
jest.mocked(confirmAsync).mockResolvedValue(true);
jest.mocked(modifyConfigAsync).mockResolvedValue({ type: 'success', config: {} as any });
jest
.mocked(createOrModifyExpoConfigAsync)
.mockResolvedValue({ type: 'success', config: {} as any });
await new ProjectInit([], commandOptions).run();
expect(confirmAsync).toHaveBeenCalled();
expect(modifyConfigAsync).toHaveBeenCalledTimes(2);
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { owner: 'jester2' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/test-project', { slug: 'testing-124' });
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledTimes(2);
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
owner: 'jester2',
});
expect(createOrModifyExpoConfigAsync).toHaveBeenCalledWith('/test-project', {
slug: 'testing-124',
});
});
});
@@ -1,4 +1,4 @@
import { getProjectConfigDescription, modifyConfigAsync } from '@expo/config';
import { getProjectConfigDescription } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Flags } from '@oclif/core';
import chalk from 'chalk';
@@ -13,7 +13,7 @@ import { AppMutation } from '../../graphql/mutations/AppMutation';
import { AppQuery } from '../../graphql/queries/AppQuery';
import Log, { link } from '../../log';
import { ora } from '../../ora';
import { getPrivateExpoConfig } from '../../project/expoConfig';
import { createOrModifyExpoConfigAsync, getPrivateExpoConfig } from '../../project/expoConfig';
import { findProjectIdByAccountNameAndSlugNullableAsync } from '../../project/fetchOrCreateProjectIDForWriteToConfigWithConfirmationAsync';
import { toAppPrivacy } from '../../project/projectUtils';
import { confirmAsync, promptAsync } from '../../prompts';
@@ -60,7 +60,7 @@ export default class ProjectInit extends EasCommand {
projectDir: string,
modifications: Partial<ExpoConfig>
): Promise<void> {
const result = await modifyConfigAsync(projectDir, modifications);
const result = await createOrModifyExpoConfigAsync(projectDir, modifications);
switch (result.type) {
case 'success':
break;
@@ -1,14 +1,16 @@
import { Flags } from '@oclif/core';
import chalk from 'chalk';
import { easJsonExistsAsync } from '../../build/configure';
import EasCommand from '../../commandUtils/EasCommand';
import { EASNonInteractiveFlag } from '../../commandUtils/flags';
import Log from '../../log';
import Log, { learnMore } from '../../log';
import { RequestedPlatform } from '../../platform';
import {
ensureEASUpdateIsConfiguredAsync,
ensureEASUpdateIsConfiguredInEasJsonAsync,
} from '../../update/configure';
import { getVcsClient } from '../../vcs';
export default class UpdateConfigure extends EasCommand {
static override description = 'configure the project to support EAS Update';
@@ -42,6 +44,8 @@ export default class UpdateConfigure extends EasCommand {
'💡 The following process will configure your project to run EAS Update. These changes only apply to your local project files and you can safely revert them at any time.'
);
await getVcsClient().ensureRepoExistsAsync();
await ensureEASUpdateIsConfiguredAsync(graphqlClient, {
exp,
projectId,
@@ -54,21 +58,14 @@ export default class UpdateConfigure extends EasCommand {
Log.addNewLineIfNone();
Log.log(`🎉 Your app is configured with EAS Update!`);
Log.newLine();
Log.log(`${chalk.bold('Next steps')}:`);
Log.newLine();
Log.log('Update a production build:');
Log.log(`1. Create a new build. Example: ${chalk.bold('eas build --profile production')}.`);
Log.log('2. Make changes in your project.');
Log.log(`3. Publish an update. Example: ${chalk.bold('eas update --channel production')}.`);
Log.log('4. Force close and reopen the app at least twice to view the update.');
Log.newLine();
Log.log('Preview an update:');
const easJsonExists = await easJsonExistsAsync(projectDir);
if (!easJsonExists) {
Log.log(`- Run ${chalk.bold('eas build:configure')} to complete your installation`);
}
Log.log(
`1. Publish an update to a branch. Example: ${chalk.bold('eas update --branch new-feature')}.`
);
Log.log(
'2. In Expo Go or a development build, navigate to Projects > [project name] > Branch > Open.'
`- ${learnMore('https://docs.expo.dev/eas-update/introduction/', {
learnMoreMessage: 'Learn more about other capabilities of EAS Update',
})}`
);
}
}
@@ -98,6 +98,7 @@ export default class UpdatePublish extends EasCommand {
required: false,
}),
message: Flags.string({
char: 'm',
description: 'A short message describing the update',
required: false,
}),
@@ -72,6 +72,7 @@ export default class UpdateRepublish extends EasCommand {
exclusive: ['branch', 'channel'],
}),
message: Flags.string({
char: 'm',
description: 'Short message describing the republished update',
required: false,
}),
@@ -151,6 +151,7 @@ export function getNewAndroidApiMock(): { [key in keyof typeof AndroidGraphqlCli
updateAndroidAppCredentialsAsync: jest.fn(),
updateAndroidAppBuildCredentialsAsync: jest.fn(),
createAndroidAppBuildCredentialsAsync: jest.fn(),
setDefaultAndroidAppBuildCredentialsAsync: jest.fn(),
getDefaultAndroidAppBuildCredentialsAsync: jest.fn(),
getAndroidAppBuildCredentialsByNameAsync: jest.fn(),
createOrUpdateAndroidAppBuildCredentialsByNameAsync: jest.fn(),
@@ -146,6 +146,16 @@ export async function updateAndroidAppBuildCredentialsAsync(
);
}
export async function setDefaultAndroidAppBuildCredentialsAsync(
graphqlClient: ExpoGraphqlClient,
buildCredentials: AndroidAppBuildCredentialsFragment
): Promise<AndroidAppBuildCredentialsFragment> {
return await AndroidAppBuildCredentialsMutation.setDefaultAndroidAppBuildCredentialsAsync(
graphqlClient,
buildCredentials.id
);
}
export async function createAndroidAppBuildCredentialsAsync(
graphqlClient: ExpoGraphqlClient,
appLookupParams: AppLookupParams,
@@ -164,14 +174,6 @@ export async function createAndroidAppBuildCredentialsAsync(
graphqlClient,
appLookupParams
);
const buildCredentialsList = androidAppCredentials.androidAppBuildCredentialsList;
const existingDefaultBuildCredentials =
buildCredentialsList.find(buildCredentials => buildCredentials.isDefault) ?? null;
if (existingDefaultBuildCredentials && isDefault) {
throw new Error(
'Cannot create new default Android Build Credentials. A set of default credentials exists already.'
);
}
return await AndroidAppBuildCredentialsMutation.createAndroidAppBuildCredentialsAsync(
graphqlClient,
@@ -5,6 +5,7 @@ import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../../../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import {
AndroidAppBuildCredentials,
AndroidAppBuildCredentialsFragment,
AndroidAppBuildCredentialsInput,
CreateAndroidAppBuildCredentialsMutation,
@@ -55,6 +56,37 @@ export const AndroidAppBuildCredentialsMutation = {
);
return data.androidAppBuildCredentials.createAndroidAppBuildCredentials;
},
async setDefaultAndroidAppBuildCredentialsAsync(
graphqlClient: ExpoGraphqlClient,
androidAppBuildCredentialsId: string
): Promise<AndroidAppBuildCredentialsFragment> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<AndroidAppBuildCredentials>(
gql`
mutation AndroidAppBuildCredentialsMutation(
$androidAppBuildCredentialsId: ID!
$isDefault: Boolean!
) {
androidAppBuildCredentials {
setDefault(id: $androidAppBuildCredentialsId, isDefault: $isDefault) {
id
...AndroidAppBuildCredentialsFragment
}
}
}
${print(AndroidAppBuildCredentialsFragmentNode)}
`,
{
androidAppBuildCredentialsId,
isDefault: true,
}
)
.toPromise()
);
assert(data, `GraphQL: 'setDefault' not defined in server response ${JSON.stringify(data)}}`);
return data;
},
async setKeystoreAsync(
graphqlClient: ExpoGraphqlClient,
androidAppBuildCredentialsId: string,
@@ -513,6 +513,20 @@ export const CapabilityMapping: CapabilityClassifier[] = [
validateOptions: createValidateStringArrayOptions(['app-usage', 'system-installation']),
getOptions: getDefinedOptions,
},
{
name: 'Apple Pay Later Merchandising',
entitlement: 'com.apple.developer.pay-later-merchandising',
capability: CapabilityType.APPLE_PAY_LATER_MERCHANDISING,
validateOptions: createValidateStringArrayOptions(['payinfour-merchandising']),
getOptions: getDefinedOptions,
},
{
name: 'Sensitive Content Analysis',
entitlement: 'com.apple.developer.sensitivecontentanalysis.client',
capability: CapabilityType.SENSITIVE_CONTENT_ANALYSIS,
validateOptions: createValidateStringArrayOptions(['analysis']),
getOptions: getDefinedOptions,
},
{
// Not in Xcode
// https://developer-mdn.apple.com/documentation/devicecheck/preparing_to_use_the_app_attest_service
@@ -698,6 +712,36 @@ export const CapabilityMapping: CapabilityClassifier[] = [
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.shared-with-you.collaboration',
name: 'Messages Collaboration',
capability: CapabilityType.MESSAGES_COLLABORATION,
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.submerged-shallow-depth-and-pressure',
name: 'Shallow Depth and Pressure',
capability: CapabilityType.SHALLOW_DEPTH_PRESSURE,
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.proximity-reader.identity.display',
name: 'Tap to Present ID on iPhone (Display Only)',
capability: CapabilityType.TAP_TO_DISPLAY_ID,
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
{
entitlement: 'com.apple.developer.matter.allow-setup-payload',
name: 'Matter Allow Setup Payload',
capability: CapabilityType.MATTER_ALLOW_SETUP_PAYLOAD,
validateOptions: validateBooleanOptions,
getOptions: getBooleanOptions,
},
// VMNET
// These don't appear to have entitlements, so it's unclear how we can automatically enable / disable them at this time.
// TODO: Maybe add a warning about manually enabling features?
@@ -18,6 +18,7 @@ export enum AndroidActionType {
GoBackToCaller,
GoBackToHighLevelActions,
CreateKeystore,
SetDefaultKeystore,
DownloadKeystore,
RemoveKeystore,
CreateFcm,
@@ -52,6 +52,11 @@ export const buildCredentialsActions: ActionInfo[] = [
title: 'Set up a new keystore',
scope: Scope.Project,
},
{
value: AndroidActionType.SetDefaultKeystore,
title: 'Change default keystore',
scope: Scope.Project,
},
{
value: AndroidActionType.DownloadKeystore,
title: 'Download existing keystore',
@@ -0,0 +1,42 @@
import { AndroidAppBuildCredentialsFragment } from '../../graphql/generated';
import Log from '../../log';
import { confirmAsync } from '../../prompts';
import { promptForNameAsync } from '../android/actions/BuildCredentialsUtils';
import { CreateKeystore } from '../android/actions/CreateKeystore';
import { AppLookupParams } from '../android/api/GraphqlClient';
import { CredentialsContext } from '../context';
export class CreateAndroidBuildCredentials {
constructor(private app: AppLookupParams) {}
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment> {
const name = await promptForNameAsync();
const buildCredentialsList = await ctx.android.getAndroidAppBuildCredentialsListAsync(
ctx.graphqlClient,
this.app
);
let isDefault = true;
if (buildCredentialsList.length > 0) {
isDefault = await confirmAsync({
message: 'Do you want to set this as your default build credentials?',
initial: false,
});
}
const keystore = await new CreateKeystore(this.app.account).runAsync(ctx);
const createAndroidCredentials = await ctx.android.createAndroidAppBuildCredentialsAsync(
ctx.graphqlClient,
this.app,
{
name,
isDefault,
androidKeystoreId: keystore.id,
}
);
Log.succeed(`Created Android build credentials ${createAndroidCredentials.name}`);
return createAndroidCredentials;
}
}
@@ -14,7 +14,6 @@ import {
} from '../android/actions/BuildCredentialsUtils';
import { CreateFcm } from '../android/actions/CreateFcm';
import { CreateGoogleServiceAccountKey } from '../android/actions/CreateGoogleServiceAccountKey';
import { CreateKeystore } from '../android/actions/CreateKeystore';
import { DownloadKeystore } from '../android/actions/DownloadKeystore';
import { RemoveFcm } from '../android/actions/RemoveFcm';
import { SelectAndRemoveGoogleServiceAccountKey } from '../android/actions/RemoveGoogleServiceAccountKey';
@@ -36,13 +35,11 @@ import {
gsaKeyActions,
highLevelActions,
} from './AndroidActions';
import { CreateAndroidBuildCredentials } from './CreateAndroidBuildCredentials';
import { Action, PressAnyKeyToContinue } from './HelperActions';
import {
SelectAndroidBuildCredentials,
SelectAndroidBuildCredentialsResultType,
SelectExistingAndroidBuildCredentials,
} from './SelectAndroidBuildCredentials';
import { SelectExistingAndroidBuildCredentials } from './SelectAndroidBuildCredentials';
import { SelectBuildProfileFromEasJson } from './SelectBuildProfileFromEasJson';
import { SetDefaultAndroidKeystore } from './SetDefaultAndroidKeystore';
export class ManageAndroid {
constructor(private callingAction: Action, private projectDir: string) {}
@@ -163,31 +160,9 @@ export class ManageAndroid {
);
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx, gradleContext);
if (action === AndroidActionType.CreateKeystore) {
const selectBuildCredentialsResult = await new SelectAndroidBuildCredentials(
appLookupParams
).runAsync(ctx);
const keystore = await new CreateKeystore(appLookupParams.account).runAsync(ctx);
if (
selectBuildCredentialsResult.resultType ===
SelectAndroidBuildCredentialsResultType.CREATE_REQUEST
) {
await ctx.android.createAndroidAppBuildCredentialsAsync(
ctx.graphqlClient,
appLookupParams,
{
...selectBuildCredentialsResult.result,
androidKeystoreId: keystore.id,
}
);
} else {
await ctx.android.updateAndroidAppBuildCredentialsAsync(
ctx.graphqlClient,
selectBuildCredentialsResult.result,
{
androidKeystoreId: keystore.id,
}
);
}
await new CreateAndroidBuildCredentials(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.SetDefaultKeystore) {
await new SetDefaultAndroidKeystore(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.DownloadKeystore) {
const buildCredentials = await new SelectExistingAndroidBuildCredentials(
appLookupParams
@@ -0,0 +1,45 @@
import { AndroidAppBuildCredentialsFragment } from '../../graphql/generated';
import Log from '../../log';
import { promptAsync } from '../../prompts';
import { sortBuildCredentials } from '../android/actions/BuildCredentialsUtils';
import { AppLookupParams } from '../android/api/GraphqlClient';
import { CredentialsContext } from '../context';
export class SetDefaultAndroidKeystore {
constructor(private app: AppLookupParams) {}
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment | undefined> {
const buildCredentialsList = await ctx.android.getAndroidAppBuildCredentialsListAsync(
ctx.graphqlClient,
this.app
);
if (buildCredentialsList.length === 0) {
Log.log(`You don't have any Android build credentials`);
return;
}
const sortedBuildCredentialsList = sortBuildCredentials(buildCredentialsList);
const sortedBuildCredentialsChoices = sortedBuildCredentialsList.map(buildCredentials => ({
title: buildCredentials.isDefault
? `${buildCredentials.name} (Default)`
: buildCredentials.name,
value: buildCredentials,
}));
const { buildCredentialsResult } = await promptAsync({
type: 'select',
name: 'buildCredentialsResult',
message: 'Select build credentials',
choices: [...sortedBuildCredentialsChoices, { title: 'Cancel', value: null }],
});
if (!buildCredentialsResult?.androidKeystore) {
return;
}
Log.log('Updating the default build credentials for this project...');
return await ctx.android.setDefaultAndroidAppBuildCredentialsAsync(ctx.graphqlClient, {
...buildCredentialsResult,
isDefault: true,
});
}
}
+65 -13
View File
@@ -1164,6 +1164,7 @@ export type AppBuildsPaginatedArgs = {
export type AppChannelsPaginatedArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
filter?: InputMaybe<ChannelFilterInput>;
first?: InputMaybe<Scalars['Int']>;
last?: InputMaybe<Scalars['Int']>;
};
@@ -1363,6 +1364,7 @@ export type AppInput = {
export type AppInsights = {
__typename?: 'AppInsights';
hasEventsFromExpoInsightsClientModule: Scalars['Boolean'];
totalUniqueUsers?: Maybe<Scalars['Int']>;
uniqueUsersByAppVersionOverTime: UniqueUsersOverTimeData;
uniqueUsersByPlatformOverTime: UniqueUsersOverTimeData;
@@ -1980,6 +1982,43 @@ export enum AuthProtocolType {
Oidc = 'OIDC'
}
export type BackgroundJobReceipt = {
__typename?: 'BackgroundJobReceipt';
account: Account;
createdAt: Scalars['DateTime'];
errorCode?: Maybe<Scalars['String']>;
errorMessage?: Maybe<Scalars['String']>;
id: Scalars['ID'];
resultId?: Maybe<Scalars['ID']>;
resultType: BackgroundJobResultType;
state: BackgroundJobState;
tries: Scalars['Int'];
updatedAt: Scalars['DateTime'];
willRetry: Scalars['Boolean'];
};
export type BackgroundJobReceiptQuery = {
__typename?: 'BackgroundJobReceiptQuery';
/** Look up background job receipt by ID */
byId: BackgroundJobReceipt;
};
export type BackgroundJobReceiptQueryByIdArgs = {
id: Scalars['ID'];
};
export enum BackgroundJobResultType {
GithubBuild = 'GITHUB_BUILD'
}
export enum BackgroundJobState {
Failure = 'FAILURE',
InProgress = 'IN_PROGRESS',
Queued = 'QUEUED',
Success = 'SUCCESS'
}
export type Billing = {
__typename?: 'Billing';
/** History of invoices */
@@ -2480,6 +2519,10 @@ export type Card = {
last4?: Maybe<Scalars['String']>;
};
export type ChannelFilterInput = {
searchTerm?: InputMaybe<Scalars['String']>;
};
export type Charge = {
__typename?: 'Charge';
amount: Scalars['Int'];
@@ -3011,8 +3054,8 @@ export enum GitHubAppInstallationStatus {
export type GitHubAppMutation = {
__typename?: 'GitHubAppMutation';
/** Create a GitHub build for an app */
createGitHubBuild: Scalars['Boolean'];
/** Create a GitHub build for an app. Returns the ID of the background job receipt. Use BackgroundJobReceiptQuery to get the status of the job. */
createGitHubBuild: BackgroundJobReceipt;
};
@@ -4122,6 +4165,7 @@ export type RootQuery = {
/** Top-level query object for querying Apple Teams. */
appleTeam: AppleTeamQuery;
asset: AssetQuery;
backgroundJobReceipt: BackgroundJobReceiptQuery;
buildJobs: BuildJobQuery;
buildOrBuildJob: BuildOrBuildJobQuery;
/** Top-level query object for querying BuildPublicData publicly. */
@@ -4221,6 +4265,7 @@ export type SsoUser = Actor & UserActor & {
/** Coalesced project activity for all apps belonging to all accounts this user belongs to. Only resolves for the viewer. */
activityTimelineProjectActivities: Array<ActivityTimelineProjectActivity>;
appCount: Scalars['Int'];
/** @deprecated No longer supported */
appetizeCode?: Maybe<Scalars['String']>;
/** Apps this user has published. If this user is the viewer, this field returns the apps the user has access to. */
apps: Array<App>;
@@ -4238,11 +4283,14 @@ export type SsoUser = Actor & UserActor & {
fullName?: Maybe<Scalars['String']>;
/** GitHub account linked to a user */
githubUser?: Maybe<GitHubUser>;
/** @deprecated No longer supported */
githubUsername?: Maybe<Scalars['String']>;
id: Scalars['ID'];
/** @deprecated No longer supported */
industry?: Maybe<Scalars['String']>;
isExpoAdmin: Scalars['Boolean'];
lastName?: Maybe<Scalars['String']>;
/** @deprecated No longer supported */
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
/** Associated accounts */
@@ -4250,6 +4298,7 @@ export type SsoUser = Actor & UserActor & {
profilePhoto: Scalars['String'];
/** Snacks associated with this account */
snacks: Array<Snack>;
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
};
@@ -4291,11 +4340,7 @@ export type SsoUserSnacksArgs = {
export type SsoUserDataInput = {
firstName?: InputMaybe<Scalars['String']>;
githubUsername?: InputMaybe<Scalars['String']>;
industry?: InputMaybe<Scalars['String']>;
lastName?: InputMaybe<Scalars['String']>;
location?: InputMaybe<Scalars['String']>;
twitterUsername?: InputMaybe<Scalars['String']>;
};
export type SsoUserQuery = {
@@ -4748,6 +4793,7 @@ export type Update = ActivityTimelineProjectActivity & {
export type UpdateBranch = {
__typename?: 'UpdateBranch';
app: App;
appId: Scalars['ID'];
createdAt: Scalars['DateTime'];
id: Scalars['ID'];
@@ -4809,6 +4855,7 @@ export type UpdateBranchMutationPublishUpdateGroupsArgs = {
export type UpdateChannel = {
__typename?: 'UpdateChannel';
app: App;
appId: Scalars['ID'];
branchMapping: Scalars['String'];
createdAt: Scalars['DateTime'];
@@ -4960,6 +5007,7 @@ export type User = Actor & UserActor & {
/** Coalesced project activity for all apps belonging to all accounts this user belongs to. Only resolves for the viewer. */
activityTimelineProjectActivities: Array<ActivityTimelineProjectActivity>;
appCount: Scalars['Int'];
/** @deprecated No longer supported */
appetizeCode?: Maybe<Scalars['String']>;
/** Apps this user has published */
apps: Array<App>;
@@ -4979,16 +5027,19 @@ export type User = Actor & UserActor & {
fullName?: Maybe<Scalars['String']>;
/** GitHub account linked to a user */
githubUser?: Maybe<GitHubUser>;
/** @deprecated No longer supported */
githubUsername?: Maybe<Scalars['String']>;
/** Whether this user has any pending user invitations. Only resolves for the viewer. */
hasPendingUserInvitations: Scalars['Boolean'];
id: Scalars['ID'];
/** @deprecated No longer supported */
industry?: Maybe<Scalars['String']>;
isExpoAdmin: Scalars['Boolean'];
/** @deprecated This field no longer exists */
/** @deprecated No longer supported */
isLegacy: Scalars['Boolean'];
isSecondFactorAuthenticationEnabled: Scalars['Boolean'];
lastName?: Maybe<Scalars['String']>;
/** @deprecated No longer supported */
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
/** Pending UserInvitations for this user. Only resolves for the viewer. */
@@ -5000,6 +5051,7 @@ export type User = Actor & UserActor & {
secondFactorDevices: Array<UserSecondFactorDevice>;
/** Snacks associated with this account */
snacks: Array<Snack>;
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
};
@@ -5050,6 +5102,7 @@ export type UserActor = {
*/
activityTimelineProjectActivities: Array<ActivityTimelineProjectActivity>;
appCount: Scalars['Int'];
/** @deprecated No longer supported */
appetizeCode?: Maybe<Scalars['String']>;
/** Apps this user has published */
apps: Array<App>;
@@ -5071,11 +5124,14 @@ export type UserActor = {
fullName?: Maybe<Scalars['String']>;
/** GitHub account linked to a user */
githubUser?: Maybe<GitHubUser>;
/** @deprecated No longer supported */
githubUsername?: Maybe<Scalars['String']>;
id: Scalars['ID'];
/** @deprecated No longer supported */
industry?: Maybe<Scalars['String']>;
isExpoAdmin: Scalars['Boolean'];
lastName?: Maybe<Scalars['String']>;
/** @deprecated No longer supported */
location?: Maybe<Scalars['String']>;
notificationSubscriptions: Array<NotificationSubscription>;
/** Associated accounts */
@@ -5083,6 +5139,7 @@ export type UserActor = {
profilePhoto: Scalars['String'];
/** Snacks associated with this user's personal account */
snacks: Array<Snack>;
/** @deprecated No longer supported */
twitterUsername?: Maybe<Scalars['String']>;
username: Scalars['String'];
};
@@ -5141,17 +5198,12 @@ export type UserActorQueryByUsernameArgs = {
};
export type UserDataInput = {
appetizeCode?: InputMaybe<Scalars['String']>;
email?: InputMaybe<Scalars['String']>;
firstName?: InputMaybe<Scalars['String']>;
fullName?: InputMaybe<Scalars['String']>;
githubUsername?: InputMaybe<Scalars['String']>;
id?: InputMaybe<Scalars['ID']>;
industry?: InputMaybe<Scalars['String']>;
lastName?: InputMaybe<Scalars['String']>;
location?: InputMaybe<Scalars['String']>;
profilePhoto?: InputMaybe<Scalars['String']>;
twitterUsername?: InputMaybe<Scalars['String']>;
username?: InputMaybe<Scalars['String']>;
};
@@ -6156,7 +6208,7 @@ export type ViewUpdateGroupsOnAppQuery = { __typename?: 'RootQuery', app: { __ty
export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
export type CurrentUserQuery = { __typename?: 'RootQuery', meActor?: { __typename: 'Robot', firstName?: string | null, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'SSOUser', username: string, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'User', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | null };
export type CurrentUserQuery = { __typename?: 'RootQuery', meActor?: { __typename: 'Robot', firstName?: string | null, id: string, featureGates: any, isExpoAdmin: boolean, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'SSOUser', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | { __typename: 'User', username: string, id: string, featureGates: any, isExpoAdmin: boolean, primaryAccount: { __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }, accounts: Array<{ __typename?: 'Account', id: string, name: string, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> }> } | null };
export type WebhooksByAppIdQueryVariables = Exact<{
appId: Scalars['String'];
@@ -16,7 +16,7 @@ export const UserQuery = {
meActor {
__typename
id
... on User {
... on UserActor {
username
primaryAccount {
id
@@ -26,9 +26,6 @@ export const UserQuery = {
... on Robot {
firstName
}
... on SSOUser {
username
}
accounts {
id
...AccountFragment
@@ -41,7 +38,7 @@ export const UserQuery = {
`,
{},
{
additionalTypenames: ['User'],
additionalTypenames: ['User', 'SSOUser'],
}
)
.toPromise()
@@ -0,0 +1,62 @@
import { getConfigFilePaths, modifyConfigAsync } from '@expo/config';
import JsonFile from '@expo/json-file';
import { writeFileSync } from 'fs-extra';
import { createOrModifyExpoConfigAsync } from '../expoConfig';
jest.mock('fs-extra');
jest.mock('@expo/config');
jest.mock('@expo/json-file');
beforeEach(() => {
jest.resetAllMocks();
});
describe('expoConfig', () => {
describe('createOrModifyExpoConfigAsync', () => {
it('should create a new app config file if it does not exist', async () => {
jest.mocked(getConfigFilePaths).mockReturnValue({
staticConfigPath: null,
dynamicConfigPath: null,
});
await createOrModifyExpoConfigAsync('/app', {});
expect(writeFileSync).toHaveBeenCalledWith('/app/app.json', '{\n "expo": {}\n}');
});
it('should delegate to modifyConfigAsync if ', async () => {
jest.mocked(getConfigFilePaths).mockReturnValue({
staticConfigPath: '/app/app.json',
dynamicConfigPath: null,
});
jest.mocked(JsonFile.readAsync).mockResolvedValue({ expo: {} });
await createOrModifyExpoConfigAsync('/app', {});
// modifyConfigAsync is mocked so this shouldn't be called
expect(writeFileSync).not.toHaveBeenCalled();
});
it('should modify an existing config file if it exists', async () => {
jest.mocked(getConfigFilePaths).mockReturnValue({
staticConfigPath: '/app/app.json',
dynamicConfigPath: null,
});
jest.mocked(JsonFile.readAsync).mockResolvedValue({ expo: {} });
await createOrModifyExpoConfigAsync('/app', { owner: 'ccheever' });
expect(modifyConfigAsync).toHaveBeenCalledWith('/app', { owner: 'ccheever' });
});
it('adds expo key if app.json is missing it', async () => {
jest.mocked(getConfigFilePaths).mockReturnValue({
staticConfigPath: '/app/app.json',
dynamicConfigPath: null,
});
jest.mocked(JsonFile.readAsync).mockResolvedValue({ name: 'App' });
await createOrModifyExpoConfigAsync('/app', { owner: 'ccheever' });
expect(JsonFile.writeAsync).toHaveBeenCalledWith('/app/app.json', { name: 'App', expo: {} });
expect(modifyConfigAsync).toHaveBeenCalledWith('/app', { owner: 'ccheever' });
});
});
});
+66 -1
View File
@@ -1,5 +1,9 @@
import { ExpoConfig, getConfig } from '@expo/config';
import { ExpoConfig, getConfig, getConfigFilePaths, modifyConfigAsync } from '@expo/config';
import { Env } from '@expo/eas-build-job';
import JsonFile from '@expo/json-file';
import fs from 'fs-extra';
import Joi from 'joi';
import path from 'path';
export type PublicExpoConfig = Omit<
ExpoConfig,
@@ -19,6 +23,21 @@ interface ExpoConfigOptionsInternal extends ExpoConfigOptions {
isPublicConfig?: boolean;
}
export async function createOrModifyExpoConfigAsync(
projectDir: string,
exp: Partial<ExpoConfig>,
readOptions?: { skipSDKVersionRequirement?: boolean }
): ReturnType<typeof modifyConfigAsync> {
ensureExpoConfigExists(projectDir);
await ensureStaticExpoConfigIsValidAsync(projectDir);
if (readOptions) {
return modifyConfigAsync(projectDir, exp, readOptions);
} else {
return modifyConfigAsync(projectDir, exp);
}
}
function getExpoConfigInternal(
projectDir: string,
opts: ExpoConfigOptionsInternal = {}
@@ -33,19 +52,65 @@ function getExpoConfigInternal(
skipSDKVersionRequirement: true,
...(opts.isPublicConfig ? { isPublicConfig: true } : {}),
});
const { error } = MinimalAppConfigSchema.validate(exp, {
allowUnknown: true,
abortEarly: true,
});
if (error) {
throw new Error(`Invalid app config.\n${error.message}`);
}
return exp;
} finally {
process.env = originalProcessEnv;
}
}
const MinimalAppConfigSchema = Joi.object({
slug: Joi.string().required(),
name: Joi.string().required(),
version: Joi.string(),
android: Joi.object({
versionCode: Joi.number().integer(),
}),
ios: Joi.object({
buildNumber: Joi.string(),
}),
});
export function getPrivateExpoConfig(projectDir: string, opts: ExpoConfigOptions = {}): ExpoConfig {
ensureExpoConfigExists(projectDir);
return getExpoConfigInternal(projectDir, { ...opts, isPublicConfig: false });
}
export function ensureExpoConfigExists(projectDir: string): void {
const paths = getConfigFilePaths(projectDir);
if (!paths?.staticConfigPath && !paths?.dynamicConfigPath) {
// eslint-disable-next-line node/no-sync
fs.writeFileSync(path.join(projectDir, 'app.json'), JSON.stringify({ expo: {} }, null, 2));
}
}
async function ensureStaticExpoConfigIsValidAsync(projectDir: string): Promise<void> {
const paths = getConfigFilePaths(projectDir);
if (paths?.staticConfigPath?.endsWith('app.json') && !paths?.dynamicConfigPath) {
const staticConfig = await JsonFile.readAsync(paths.staticConfigPath);
// Add the "expo" key if it doesn't exist on app.json yet, such as in
// projects initialized with RNC CLI
if (!staticConfig?.expo) {
staticConfig.expo = {};
await JsonFile.writeAsync(paths.staticConfigPath, staticConfig);
}
}
}
export function getPublicExpoConfig(
projectDir: string,
opts: ExpoConfigOptions = {}
): PublicExpoConfig {
ensureExpoConfigExists(projectDir);
return getExpoConfigInternal(projectDir, { ...opts, isPublicConfig: true });
}
+12 -2
View File
@@ -5,6 +5,7 @@ import path from 'path';
import resolveFrom from 'resolve-from';
import semver from 'semver';
import { getEASUpdateURL } from '../api';
import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { AccountFragment, AppPrivacy } from '../graphql/generated';
import { AppQuery } from '../graphql/queries/AppQuery';
@@ -16,6 +17,8 @@ export function getUsername(exp: ExpoConfig, user: Actor): string | undefined {
switch (user.__typename) {
case 'User':
return user.username;
case 'SSOUser':
return user.username;
case 'Robot':
// owner field is necessary to run `expo prebuild`
if (!exp.owner) {
@@ -25,8 +28,6 @@ export function getUsername(exp: ExpoConfig, user: Actor): string | undefined {
}
// robot users don't have usernames
return undefined;
case 'SSOUser':
throw new Error('SSO users are not supported yet.');
}
}
@@ -66,6 +67,11 @@ export function isExpoUpdatesInstalled(projectDir: string): boolean {
return !!(packageJson.dependencies && 'expo-updates' in packageJson.dependencies);
}
export function isExpoUpdatesInstalledAsDevDependency(projectDir: string): boolean {
const packageJson = getPackageJson(projectDir);
return !!(packageJson.devDependencies && 'expo-updates' in packageJson.devDependencies);
}
export function isExpoUpdatesInstalledOrAvailable(
projectDir: string,
sdkVersion?: string
@@ -78,6 +84,10 @@ export function isExpoUpdatesInstalledOrAvailable(
return isExpoUpdatesInstalled(projectDir);
}
export function isUsingEASUpdate(exp: ExpoConfig, projectId: string): boolean {
return exp.updates?.url === getEASUpdateURL(projectId);
}
export async function validateAppVersionRuntimePolicySupportAsync(
projectDir: string,
exp: ExpoConfig
@@ -94,6 +94,7 @@ function mockUpdateChannel({
}): UpdateChannel {
return {
id: 'a2a1fa12-9d6a-433a-a432-49c64ef8439f',
app: {} as App,
name: channelName ?? 'default-channel-name',
createdAt: '2022-12-07T02:24:29.786Z',
appId: '123',
@@ -109,6 +110,7 @@ function mockUpdateBranches(branchNames: string[]): UpdateBranch[] {
return branchNames.map(branchName => ({
id: 'f9dc4dbb-663f-4a19-8cf2-a783b484d2db',
name: branchName ?? 'default-branch-name',
app: {} as App,
appId: '123',
createdAt: '2022-12-07T02:24:29.786Z',
updatedAt: '2022-12-07T02:24:29.786Z',
@@ -140,6 +142,7 @@ function mockUpdateBranches(branchNames: string[]): UpdateBranch[] {
branch: {
id: 'f9dc4dbb-663f-4a19-8cf2-a783b484d2db',
name: 'production3',
app: {} as App,
appId: '123',
createdAt: '2022-12-07T02:24:29.786Z',
updatedAt: '2022-12-07T02:24:29.786Z',
+31 -20
View File
@@ -1,4 +1,3 @@
import { modifyConfigAsync } from '@expo/config';
import { ExpoConfig } from '@expo/config-types';
import { Platform, Workflow } from '@expo/eas-build-job';
import { EasJsonAccessor } from '@expo/eas-json';
@@ -10,8 +9,10 @@ import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGr
import { AppPlatform } from '../graphql/generated';
import Log, { learnMore } from '../log';
import { RequestedPlatform, appPlatformDisplayNames } from '../platform';
import { createOrModifyExpoConfigAsync } from '../project/expoConfig';
import {
installExpoUpdatesAsync,
isExpoUpdatesInstalledAsDevDependency,
isExpoUpdatesInstalledOrAvailable,
} from '../project/projectUtils';
import { resolveWorkflowPerPlatformAsync } from '../project/workflow';
@@ -128,7 +129,7 @@ async function ensureEASUpdatesIsConfiguredInExpoConfigAsync({
}
const mergedExp = mergeExpoConfig(exp, modifyConfig);
const result = await modifyConfigAsync(projectDir, mergedExp);
const result = await createOrModifyExpoConfigAsync(projectDir, mergedExp);
switch (result.type) {
case 'success':
@@ -168,22 +169,29 @@ function logEasUpdatesAutoConfig({
);
}
if (modifyConfig.android?.runtimeVersion ?? modifyConfig.runtimeVersion) {
const androidRuntime = modifyConfig.android?.runtimeVersion ?? modifyConfig.runtimeVersion;
const iosRuntime = modifyConfig.ios?.runtimeVersion ?? modifyConfig.runtimeVersion;
if (androidRuntime && iosRuntime && androidRuntime === iosRuntime) {
Log.withTick(
`Configured runtimeVersion for ${
appPlatformDisplayNames[AppPlatform.Android]
} with "${JSON.stringify(
modifyConfig.android?.runtimeVersion ?? modifyConfig.runtimeVersion
)}"`
);
}
if (modifyConfig.ios?.runtimeVersion ?? modifyConfig.runtimeVersion) {
Log.withTick(
`Configured runtimeVersion for ${
`Configured runtimeVersion for ${appPlatformDisplayNames[AppPlatform.Android]} and ${
appPlatformDisplayNames[AppPlatform.Ios]
} with "${JSON.stringify(modifyConfig.ios?.runtimeVersion ?? modifyConfig.runtimeVersion)}"`
} with "${modifyConfig.android?.runtimeVersion ?? modifyConfig.runtimeVersion}"`
);
} else {
if (androidRuntime) {
Log.withTick(
`Configured runtimeVersion for ${appPlatformDisplayNames[AppPlatform.Android]} with "${
modifyConfig.android?.runtimeVersion ?? modifyConfig.runtimeVersion
}"`
);
}
if (iosRuntime) {
Log.withTick(
`Configured runtimeVersion for ${appPlatformDisplayNames[AppPlatform.Ios]} with "${
modifyConfig.ios?.runtimeVersion ?? modifyConfig.runtimeVersion
}"`
);
}
}
}
@@ -265,9 +273,7 @@ export async function ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir: stri
Log.warn(
`EAS Build is not configured. If you'd like to use EAS Build with EAS Update, run ${chalk.bold(
'eas build:configure'
)}, then re-run ${chalk.bold('eas update:configure')} to configure ${chalk.bold(
'eas.json'
)} with EAS Update.`
)}.`
);
return;
}
@@ -342,9 +348,14 @@ export async function ensureEASUpdateIsConfiguredAsync(
projectDir,
expWithoutUpdates.sdkVersion
);
if (!hasExpoUpdates) {
const hasExpoUpdatesInDevDependencies = isExpoUpdatesInstalledAsDevDependency(projectDir);
if (!hasExpoUpdates && !hasExpoUpdatesInDevDependencies) {
await installExpoUpdatesAsync(projectDir, { silent: false });
Log.withTick('Installed expo updates');
Log.withTick('Installed expo-updates');
} else if (hasExpoUpdatesInDevDependencies) {
Log.warn(
`The "expo-updates" package is installed as a dev dependency. This is not recommended. Move "expo-updates" to your main dependencies.`
);
}
// Bail out if using a platform that doesn't require runtime versions
+23 -2
View File
@@ -13,6 +13,7 @@ import { UserQuery } from '../graphql/queries/UserQuery';
import Log, { learnMore } from '../log';
import { promptAsync, selectAsync } from '../prompts';
import { getStateJsonPath } from '../utils/paths';
import { fetchSessionSecretAndSsoUserAsync } from './fetchSessionSecretAndSsoUser';
import { fetchSessionSecretAndUserAsync } from './fetchSessionSecretAndUser';
type UserSettingsData = {
@@ -25,7 +26,7 @@ type SessionData = {
// These fields are potentially used by Expo CLI.
userId: string;
username: string;
currentConnection: 'Username-Password-Authentication';
currentConnection: 'Username-Password-Authentication' | 'Browser-Flow-Authentication';
};
export enum UserSecondFactorDeviceMethod {
@@ -147,6 +148,7 @@ export default class SessionManager {
public async showLoginPromptAsync({
nonInteractive = false,
printNewLine = false,
sso = false,
} = {}): Promise<void> {
if (nonInteractive) {
Errors.error(
@@ -162,7 +164,16 @@ export default class SessionManager {
Log.newLine();
}
Log.log('Log in to EAS');
if (sso) {
await this.ssoLoginAsync();
return;
}
Log.log(
`Log in to EAS with email or username (exit and run ${chalk.bold(
'eas login'
)} for other options)`
);
const { username, password } = await promptAsync([
{
@@ -194,6 +205,16 @@ export default class SessionManager {
}
}
private async ssoLoginAsync(): Promise<void> {
const { sessionSecret, id, username } = await fetchSessionSecretAndSsoUserAsync();
await this.setSessionAsync({
sessionSecret,
userId: id,
username,
currentConnection: 'Browser-Flow-Authentication',
});
}
private async loginAsync(input: {
username: string;
password: string;
+1 -1
View File
@@ -3,7 +3,7 @@ import { CurrentUserQuery, Robot, SsoUser, User } from '../graphql/generated';
export type Actor = NonNullable<CurrentUserQuery['meActor']>;
/**
* Resolve the name of the actor, either normal user or robot user.
* Resolve the name of the actor, either normal user, sso user or robot user.
* This should be used whenever the "current user" needs to be displayed.
* The display name CANNOT be used as project owner.
*/
@@ -9,6 +9,7 @@ import Log from '../../log';
import { promptAsync, selectAsync } from '../../prompts';
import { getStateJsonPath } from '../../utils/paths';
import SessionManager, { UserSecondFactorDeviceMethod } from '../SessionManager';
import { fetchSessionSecretAndSsoUserAsync } from '../fetchSessionSecretAndSsoUser';
import { fetchSessionSecretAndUserAsync } from '../fetchSessionSecretAndUser';
jest.mock('../../prompts');
@@ -24,6 +25,7 @@ jest.mock('../../graphql/queries/UserQuery', () => ({
},
}));
jest.mock('../fetchSessionSecretAndUser');
jest.mock('../fetchSessionSecretAndSsoUser');
jest.mock('../../api');
const authStub: any = {
@@ -154,6 +156,29 @@ describe(SessionManager, () => {
});
});
describe('ssoLoginAsync', () => {
it('saves user data to ~/.expo/state.json', async () => {
jest.mocked(fetchSessionSecretAndSsoUserAsync).mockResolvedValue({
sessionSecret: 'SESSION_SECRET',
id: 'USER_ID',
username: 'USERNAME',
});
const sessionManager = new SessionManager(analytics);
await sessionManager['ssoLoginAsync']();
expect(await fs.readFile(getStateJsonPath(), 'utf8')).toMatchInlineSnapshot(`
"{
"auth": {
"sessionSecret": "SESSION_SECRET",
"userId": "USER_ID",
"username": "USERNAME",
"currentConnection": "Browser-Flow-Authentication"
}
}
"
`);
});
});
describe('logoutAsync', () => {
it('removes the session secret', async () => {
jest.mocked(fetchSessionSecretAndUserAsync).mockResolvedValue({
@@ -230,6 +255,45 @@ describe(SessionManager, () => {
}
);
});
it('calls regular login if the sso flag is false', async () => {
jest
.mocked(promptAsync)
.mockImplementationOnce(async () => ({ username: 'USERNAME', password: 'PASSWORD' }))
.mockImplementation(() => {
throw new Error("shouldn't happen");
});
const sessionManager = new SessionManager(analytics);
// Regular login
await sessionManager.showLoginPromptAsync({ sso: false });
expect(fetchSessionSecretAndUserAsync).toHaveBeenCalled();
});
it('calls regular login if the sso flag is undefined', async () => {
jest
.mocked(promptAsync)
.mockImplementationOnce(async () => ({ username: 'USERNAME', password: 'PASSWORD' }))
.mockImplementation(() => {
throw new Error("shouldn't happen");
});
const sessionManager = new SessionManager(analytics);
// Regular login
await sessionManager.showLoginPromptAsync({ sso: undefined });
expect(fetchSessionSecretAndUserAsync).toHaveBeenCalled();
});
it('calls SSO login if the sso flag is true', async () => {
const sessionManager = new SessionManager(analytics);
// SSO login
await sessionManager.showLoginPromptAsync({ sso: true });
expect(promptAsync).not.toHaveBeenCalled();
expect(fetchSessionSecretAndSsoUserAsync).toHaveBeenCalled();
});
});
describe('retryUsernamePasswordAuthWithOTPAsync', () => {
@@ -21,6 +21,26 @@ const userStub: Actor = {
featureGates: {},
};
const ssoUserStub: Actor = {
__typename: 'SSOUser',
id: 'ssoUserId',
username: 'ssoUsername',
primaryAccount: {
id: 'account_id_888',
name: 'ssoUsername',
users: [{ role: Role.Owner, actor: { id: 'ssoUserId' } }],
},
accounts: [
{
id: 'account_id_888',
name: 'ssoUsername',
users: [{ role: Role.Owner, actor: { id: 'ssoUserId' } }],
},
],
isExpoAdmin: false,
featureGates: {},
};
const robotStub: Actor = {
__typename: 'Robot',
id: 'userId',
@@ -35,10 +55,14 @@ describe('getActorDisplayName', () => {
expect(getActorDisplayName()).toBe('unknown');
});
it('returns username for user actors', () => {
it('returns username for regular user actors', () => {
expect(getActorDisplayName(userStub)).toBe(userStub.username);
});
it('returns username for SSO user actors', () => {
expect(getActorDisplayName(ssoUserStub)).toBe(`${ssoUserStub.username}`);
});
it('returns firstName with robot prefix for robot actors', () => {
expect(getActorDisplayName(robotStub)).toBe(`${robotStub.firstName} (robot)`);
});
+1 -1
View File
@@ -2,7 +2,7 @@ import { AccountFragment } from '../graphql/generated';
import { Actor } from './User';
export function ensureActorHasPrimaryAccount(user: Actor): AccountFragment {
if (user.__typename === 'User') {
if (user.__typename === 'User' || user.__typename === 'SSOUser') {
return user.primaryAccount;
}
throw new Error('This action is not supported for robot users.');
@@ -0,0 +1,80 @@
import openBrowserAsync from 'better-opn';
import http from 'http';
import { Socket } from 'node:net';
import querystring from 'querystring';
import Log from '../log';
export async function getSessionUsingBrowserAuthFlowAsync(options: {
expoWebsiteUrl: string;
serverPort: number;
}): Promise<string> {
const { expoWebsiteUrl, serverPort } = options;
if (!expoWebsiteUrl || !serverPort) {
throw new Error('Expo website URL and local server port are required.');
}
const scheme = 'http';
const hostname = 'localhost';
const path = '/auth/callback';
const redirectUri = `${scheme}://${hostname}:${serverPort}${path}`;
const buildExpoSsoLoginUrl = (): string => {
const data = {
app_redirect_uri: redirectUri,
};
const params = querystring.stringify(data);
return `${expoWebsiteUrl}/sso-login?${params}`;
};
// Start server and begin auth flow
const executeAuthFlow = (): Promise<string> => {
return new Promise<string>(async (resolve, reject) => {
const connections = new Set<Socket>();
const server = http.createServer(
(request: http.IncomingMessage, response: http.ServerResponse) => {
try {
if (!(request.method === 'GET' && request.url?.includes('/auth/callback'))) {
throw new Error('Unexpected SSO login response.');
}
const url = new URL(request.url, `http:${request.headers.host}`);
const sessionSecret = url.searchParams.get('session_secret');
if (!sessionSecret) {
throw new Error('Request missing session_secret search parameter.');
}
resolve(sessionSecret);
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.write(`Website login has completed. You can now close this tab.`);
response.end();
} catch (error) {
reject(error);
} finally {
server.close();
// Ensure that the server shuts down
for (const connection of connections) {
connection.destroy();
}
}
}
);
server.listen(serverPort, hostname, () => {
Log.log('Waiting for browser login...');
});
server.on('connection', connection => {
connections.add(connection);
connection.on('close', () => {
connections.delete(connection);
});
});
const authorizeUrl = buildExpoSsoLoginUrl();
openBrowserAsync(authorizeUrl);
});
};
return await executeAuthFlow();
}
@@ -0,0 +1,23 @@
import { getExpoWebsiteBaseUrl, getSsoLocalServerPortAsync } from '../api';
import { getSessionUsingBrowserAuthFlowAsync } from './expoSsoLauncher';
import { fetchUserAsync } from './fetchUser';
export async function fetchSessionSecretAndSsoUserAsync(): Promise<{
sessionSecret: string;
id: string;
username: string;
}> {
const config = {
expoWebsiteUrl: getExpoWebsiteBaseUrl(),
serverPort: await getSsoLocalServerPortAsync(),
};
const sessionSecret = await getSessionUsingBrowserAuthFlowAsync(config);
const userData = await fetchUserAsync({ sessionSecret });
return {
sessionSecret,
id: userData.id,
username: userData.username,
};
}
@@ -1,7 +1,5 @@
import gql from 'graphql-tag';
import { ApiV2Client } from '../api';
import { createGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { fetchUserAsync } from './fetchUser';
export async function fetchSessionSecretAndUserAsync({
username,
@@ -21,32 +19,10 @@ export async function fetchSessionSecretAndUserAsync({
body: { username, password, otp },
});
const { sessionSecret } = body.data;
const graphqlClient = createGraphqlClient({ accessToken: null, sessionSecret: null });
const result = await graphqlClient
.query(
gql`
query UserQuery {
viewer {
id
username
}
}
`,
{},
{
fetchOptions: {
headers: {
'expo-session': sessionSecret,
},
},
additionalTypenames: [] /* UserQuery has immutable fields */,
}
)
.toPromise();
const { data } = result;
const userData = await fetchUserAsync({ sessionSecret });
return {
sessionSecret,
id: data.viewer.id,
username: data.viewer.username,
id: userData.id,
username: userData.username,
};
}
+33
View File
@@ -0,0 +1,33 @@
import gql from 'graphql-tag';
import { createGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
export async function fetchUserAsync({
sessionSecret,
}: {
sessionSecret: string;
}): Promise<{ id: string; username: string }> {
const graphqlClient = createGraphqlClient({ accessToken: null, sessionSecret });
const result = await graphqlClient
.query(
gql`
query UserQuery {
meUserActor {
id
username
}
}
`,
{},
{
additionalTypenames: [] /* UserQuery has immutable fields */,
}
)
.toPromise();
const { data } = result;
return {
id: data.meUserActor.id,
username: data.meUserActor.username,
};
}
+16 -3
View File
@@ -5,7 +5,7 @@ import { boolish } from 'getenv';
import resolveFrom, { silent as silentResolveFrom } from 'resolve-from';
import semver from 'semver';
import Log from '../log';
import Log, { link } from '../log';
import { memoize } from './expodash/memoize';
// Aggressively returns `true` (UNVERSIONED, invalid SDK version format) to push users towards the versioned CLI.
@@ -63,8 +63,21 @@ export async function expoCommandAsync(
args: string[],
{ silent = false }: { silent?: boolean } = {}
): Promise<void> {
const expoCliPath =
silentResolveFrom(projectDir, 'expo/bin/cli') ?? resolveFrom(projectDir, 'expo/bin/cli.js');
let expoCliPath;
try {
expoCliPath =
silentResolveFrom(projectDir, 'expo/bin/cli') ?? resolveFrom(projectDir, 'expo/bin/cli.js');
} catch (e: any) {
if (e.code === 'MODULE_NOT_FOUND') {
throw new Error(
`The \`expo\` package was not found. Follow the installation directions at ${link(
'https://docs.expo.dev/bare/installing-expo-modules/'
)}`
);
}
throw e;
}
const spawnPromise = spawnAsync(expoCliPath, args, {
stdio: ['inherit', 'pipe', 'pipe'], // inherit stdin so user can install a missing expo-cli from inside this command
});
+11
View File
@@ -0,0 +1,11 @@
import freeportAsync from 'freeport-async';
/** Get a free port or throw an error. */
export async function getFreePortAsync(rangeStart: number): Promise<number> {
const port = await freeportAsync(rangeStart, { hostnames: [null, 'localhost'] });
if (!port) {
throw new Error('No available port found');
}
return port;
}
+1 -1
View File
@@ -53,7 +53,7 @@ export default class GitClient extends Client {
}
Log.warn("It looks like you haven't initialized the git repository yet.");
Log.warn('EAS Build requires you to use a git repository for your project.');
Log.warn('EAS requires you to use a git repository for your project.');
const cwd = process.cwd();
const repoRoot = PackageManagerUtils.findWorkspaceRoot(cwd) ?? cwd;
+8
View File
@@ -0,0 +1,8 @@
declare module 'freeport-async' {
interface FreePortOptions {
hostnames?: (string | null)[];
}
function freePortAsync(rangeStart: number, options?: FreePortOptions): Promise<number>;
export = freePortAsync;
}
Generated
+121 -28
View File
@@ -1324,10 +1324,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@expo/apple-utils@1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@expo/apple-utils/-/apple-utils-1.2.0.tgz#227d118089a4645b076162f3b513dfc68763ca21"
integrity sha512-MotvQqu8CNVlnl9nsISobXDjEzSMfT7U5Zk+1rhOFoJhaZhlEkARxumUFUgH6cYnK7J2mMd3YxM+G769arkEKQ==
"@expo/apple-utils@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@expo/apple-utils/-/apple-utils-1.3.1.tgz#99a2627c167af138722af9806a09a35f87115a39"
integrity sha512-ADPHXIpTWlt9tIg9yhwyuxQ6UMICWMfHgoCE1v8zzyYsa3BcKvawgkAGApYNxp2IYUKiNMqRYzViEKgq+Svk3w==
"@expo/bunyan@^4.0.0":
version "4.0.0"
@@ -1347,12 +1347,12 @@
node-forge "^1.2.1"
nullthrows "^1.1.1"
"@expo/config-plugins@6.0.2":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-6.0.2.tgz#cf07319515022ba94d9aa9fa30e0cff43a14256f"
integrity sha512-Cn01fXMHwjU042EgO9oO3Mna0o/UCrW91MQLMbJa4pXM41CYGjNgVy1EVXiuRRx/upegHhvltBw5D+JaUm8aZQ==
"@expo/config-plugins@7.2.3":
version "7.2.3"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.3.tgz#982800bf1aec3811f3e087a1e8784c82f0853672"
integrity sha512-8wBR4HH2PhPbupUNXCB1aslMD4vNYEnew26os1nCZ4vaUwcp0LeI9Zl2ycOCBVwGSdd5RNHFzK2R/OFE9P13tA==
dependencies:
"@expo/config-types" "^48.0.0"
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/json-file" "~8.2.37"
"@expo/plist" "^0.0.20"
"@expo/sdk-runtime-versions" "^1.0.0"
@@ -1363,10 +1363,10 @@
getenv "^1.0.0"
glob "7.1.6"
resolve-from "^5.0.0"
semver "^7.3.5"
semver "^7.5.3"
slash "^3.0.0"
xcode "^3.0.1"
xml2js "0.4.23"
xml2js "0.6.0"
"@expo/config-plugins@~5.0.3":
version "5.0.4"
@@ -1389,17 +1389,55 @@
xcode "^3.0.1"
xml2js "0.4.23"
"@expo/config-[email protected]", "@expo/config-types@^47.0.0":
"@expo/config-plugins@~7.2.0":
version "7.2.4"
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.4.tgz#c8d354348b746e53d70224f0bf7b87994f7c2936"
integrity sha512-TItGwmKH1GDjA5GlMkXo1A8pqeqppSK40aSVRVQaGZraUj+nuvtpWxNgEWZxWFumiatP2ocWwyWVjfmH+rJY6g==
dependencies:
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/json-file" "~8.2.37"
"@expo/plist" "^0.0.20"
"@expo/sdk-runtime-versions" "^1.0.0"
"@react-native/normalize-color" "^2.0.0"
chalk "^4.1.2"
debug "^4.3.1"
find-up "~5.0.0"
getenv "^1.0.0"
glob "7.1.6"
resolve-from "^5.0.0"
semver "^7.5.3"
slash "^3.0.0"
xcode "^3.0.1"
xml2js "0.6.0"
"@expo/[email protected]", "@expo/config-types@^49.0.0-alpha.1":
version "49.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09"
integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA==
"@expo/config-types@^47.0.0":
version "47.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-47.0.0.tgz#99eeabe0bba7a776e0f252b78beb0c574692c38d"
integrity sha512-r0pWfuhkv7KIcXMUiNACJmJKKwlTBGMw9VZHNdppS8/0Nve8HZMTkNRFQzTHW1uH3pBj8jEXpyw/2vSWDHex9g==
"@expo/config-types@^48.0.0":
version "48.0.0"
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-48.0.0.tgz#15a46921565ffeda3c3ba010701398f05193d5b3"
integrity sha512-DwyV4jTy/+cLzXGAo1xftS6mVlSiLIWZjl9DjTCLPFVgNYQxnh7htPilRv4rBhiNs7KaznWqKU70+4zQoKVT9A==
"@expo/config@8.1.2":
version "8.1.2"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.1.2.tgz#7fff28b3acefe39702e9f3ce1c9fd896a52caa80"
integrity sha512-4e7hzPj50mQIlsrzOH6XZ36O094mPfPTIDIH4yv49bWNMc7GFLTofB/lcT+QyxiLaJuC0Wlk9yOLB8DIqmtwug==
dependencies:
"@babel/code-frame" "~7.10.4"
"@expo/config-plugins" "~7.2.0"
"@expo/config-types" "^49.0.0-alpha.1"
"@expo/json-file" "^8.2.37"
getenv "^1.0.0"
glob "7.1.6"
require-from-string "^2.0.2"
resolve-from "^5.0.0"
semver "7.5.3"
slugify "^1.3.4"
sucrase "^3.20.0"
"@expo/[email protected]", "@expo/config@~7.0.2":
"@expo/config@~7.0.2":
version "7.0.3"
resolved "https://registry.yarnpkg.com/@expo/config/-/config-7.0.3.tgz#c9c634e76186de25e296485e51418f1e52966e6e"
integrity sha512-joVtB5o+NF40Tmsdp65UzryRtbnCuMbXkVO4wJnNJO4aaK0EYLdHCYSewORVqNcDfGN0LphQr8VTG2npbd9CJA==
@@ -1450,7 +1488,7 @@
json5 "^1.0.1"
write-file-atomic "^2.3.0"
"@expo/[email protected]", "@expo/json-file@~8.2.37":
"@expo/[email protected]", "@expo/json-file@^8.2.37", "@expo/json-file@~8.2.37":
version "8.2.37"
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049"
integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q==
@@ -1459,12 +1497,13 @@
json5 "^2.2.2"
write-file-atomic "^2.3.0"
"@expo/[email protected]3":
version "1.0.13"
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.13.tgz#f9d02d76867aaaa7e33b30dc5a493202da5d5414"
integrity sha512-x1dp47CCR/mohJcYhg1cv17nDP2ih5MqQcW4CJL02GpNYPlvWSR5V5203kmOdYdCWq2Rs1j45Yo9VmpS2dxSfw==
"@expo/[email protected].21":
version "1.0.21"
resolved "https://registry.yarnpkg.com/@expo/logger/-/logger-1.0.21.tgz#9271b52b8e27159cbbe3385b9a01fca3317b37c2"
integrity sha512-Vz+LHDGWUfowAwL10nBKqxrMYvO4qdZ8hLKcqUYc5mXBt+jmv7RP+8fcsMIejJEMWmYC2meO5eeCMLKKhEIgMA==
dependencies:
"@expo/bunyan" "^4.0.0"
"@types/bunyan" "^1.8.8"
bunyan "^1.8.15"
"@expo/[email protected]":
version "1.1.0"
@@ -1605,12 +1644,12 @@
dependencies:
cross-spawn "^7.0.3"
"@expo/[email protected].13":
version "1.0.13"
resolved "https://registry.yarnpkg.com/@expo/steps/-/steps-1.0.13.tgz#97d448055a8fda8c1e04b2c7c95e2e9cfae3820e"
integrity sha512-Hf8VFgwaFsvIb9/8r02/RO5eb1gDUSVyBFgBYVb3iMJvjoZXv74+mJllbh3x1EO28ai68vcEtp8uZ8Su2sLuwg==
"@expo/[email protected].23":
version "1.0.23"
resolved "https://registry.yarnpkg.com/@expo/steps/-/steps-1.0.23.tgz#a996244be55ae939636a00fdc27c9922bb4f0c42"
integrity sha512-H6rW49Dje0O/EDamhpbiYwpVltWM+057Exd7RFz8pzmPnkIAYHMXOErIftl3P79LM+ydWe5WWLX92cYU5uCFgA==
dependencies:
"@expo/logger" "1.0.13"
"@expo/logger" "1.0.21"
"@expo/spawn-async" "^1.7.0"
arg "^5.0.2"
joi "^17.7.0"
@@ -4154,6 +4193,13 @@
"@types/connect" "*"
"@types/node" "*"
"@types/bunyan@^1.8.8":
version "1.8.8"
resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.8.tgz#8d6d33f090f37c07e2a80af30ae728450a101008"
integrity sha512-Cblq+Yydg3u+sGiz2mjHjC5MPmdjY+No4qvHrF+BUhblsmSfMvsHLbOG62tPbonsqBj6sbWv1LHcsoe5Jw+/Ow==
dependencies:
"@types/node" "*"
"@types/cacheable-request@^6.0.1":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
@@ -5377,6 +5423,16 @@ builtins@^5.0.0:
dependencies:
semver "^7.0.0"
bunyan@^1.8.15:
version "1.8.15"
resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46"
integrity sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==
optionalDependencies:
dtrace-provider "~0.8"
moment "^2.19.3"
mv "~2"
safe-json-stringify "~1"
busboy@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
@@ -6529,6 +6585,13 @@ [email protected], dset@^3.1.2:
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
dtrace-provider@~0.8:
version "0.8.8"
resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e"
integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==
dependencies:
nan "^2.14.0"
duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
@@ -7455,6 +7518,11 @@ [email protected]:
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
[email protected]:
version "2.0.0"
resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4"
integrity sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==
[email protected]:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -10301,6 +10369,11 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
moment@^2.19.3:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
[email protected]:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -10350,6 +10423,11 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nan@^2.14.0:
version "2.17.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
[email protected]:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
@@ -12073,6 +12151,13 @@ [email protected], semver@^7.0.0, semver@^7.3.8:
dependencies:
lru-cache "^6.0.0"
[email protected], semver@^7.5.3:
version "7.5.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e"
integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==
dependencies:
lru-cache "^6.0.0"
[email protected], semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.4, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
@@ -13775,6 +13860,14 @@ [email protected]:
sax ">=0.6.0"
xmlbuilder "~11.0.0"
[email protected]:
version "0.6.0"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282"
integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==
dependencies:
sax ">=0.6.0"
xmlbuilder "~11.0.0"
xmlbuilder@^14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c"