Compare commits

...
Author SHA1 Message Date
Quinlan Jung 7a669bccb0 Temporary Commit at 4/23/2024, 12:39:50 PM 2024-04-23 12:39:50 -07:00
Quinlan Jung d33cfaba67 update CHANGELOG.md 2024-04-23 19:35:45 +00:00
Quinlan Jung 7363164889 Temporary Commit at 4/23/2024, 11:21:16 AM 2024-04-23 11:21:16 -07:00
Quinlan Jung 44cd3b2669 [eas-cli] amend credential removal wording (#2334)
* Temporary Commit at 4/18/2024, 8:40:55 PM

* update CHANGELOG.md
2024-04-19 10:41:18 -07:00
Szymon Dziedzic 0c706048be [ENG-9817][ci] bump @expo/eas-json version in universe after the release (#2142)
* [ci] bump `@expo/eas-json` version in universe after the release

* Update .github/workflows/release.yml

* test

* edit eas.json

* Revert "edit eas.json"

This reverts commit 3979a1b1fb.

* Revert "test"

This reverts commit 69db39f548.
2024-04-19 10:22:44 +02:00
Expo CI 211a3fb6bf update CHANGELOG.md 2024-04-15 18:29:07 +00:00
Szymon Dziedzic baeb88f5be v7.8.2 2024-04-15 20:23:12 +02:00
Szymon Dziedzic ec3c27f744 upgrade eas-cli-local-build-plugin to 1.0.100 2024-04-15 20:21:47 +02:00
Szymon Dziedzic 054732c245 Revert "v7.8.2"
This reverts commit 0f45f938b1.
2024-04-15 20:18:21 +02:00
Szymon Dziedzic 70c876776d [ci] use correct workingdir for getting x86 macos build (#2331) 2024-04-15 20:12:05 +02:00
Quinlan Jung 0f45f938b1 v7.8.2 2024-04-15 10:32:58 -07:00
Quinlan Jung c8313f36e7 [ENG-11823][2/2] move credentials endpoints to paginated (#2327)
* [eas-cli] move credentials endpoints to paginated

* switch over android creds to paginated endpoints

* update CHANGELOG.md
2024-04-15 10:19:15 -07:00
Quinlan Jung a8cde5e81d [1/2][eas-cli] paginated progress bar (#2326)
* [eas-cli] paginated progress bar

* update CHANGELOG.md
2024-04-15 10:11:29 -07:00
Will Schurman d05142f9fc [eas-cli] Fix display of errors when expo-updates CLI command fails (#2324) 2024-04-12 13:36:54 -07:00
Szymon Dziedzic 8e26c7c508 [ci] build darwin-arm64 executable as well when releasing new EAS CLI version (#2323) 2024-04-12 18:43:58 +02:00
Expo CI c29018df20 update CHANGELOG.md 2024-04-11 10:04:02 +00:00
29 changed files with 965 additions and 222 deletions

No files matched your search

+32 -1
View File
@@ -75,10 +75,13 @@ jobs:
working-directory: ${{ github.workspace }}/packages/eas-cli
run: |
yarn pretarball-ci
yarn oclif pack:tarballs --no-xz --targets darwin-x64
yarn oclif pack:tarballs --no-xz --targets darwin-x64,darwin-arm64
- id: x64
run: echo "filename=$(ls eas-*-x64.tar.gz)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
- id: arm64
run: echo "filename=$(ls eas-*-arm64.tar.gz)" >> $GITHUB_OUTPUT
working-directory: ${{ github.workspace }}/packages/eas-cli/dist
- name: Upload darwin-x64 tarball
uses: actions/upload-release-asset@v1
env:
@@ -88,6 +91,15 @@ jobs:
asset_path: packages/eas-cli/dist/${{ steps.x64.outputs.filename }}
asset_name: ${{ steps.x64.outputs.filename }}
asset_content_type: application/gzip
- name: Upload darwin-arm64 tarball
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release.outputs.upload_url }}
asset_path: packages/eas-cli/dist/${{ steps.arm64.outputs.filename }}
asset_name: ${{ steps.arm64.outputs.filename }}
asset_content_type: application/gzip
build-windows:
name: Build for Windows
runs-on: ubuntu-latest
@@ -211,3 +223,22 @@ jobs:
SLACK_USERNAME: 'EAS CLI CI'
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_FOOTER: ''
open-pr-in-universe:
name: Open a PR with `@expo/eas-json` bump in universe
needs: publish-to-npm
runs-on: ubuntu-latest
steps:
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
eas-json:
- 'packages/eas-json/**'
- name: Open a PR with `@expo/eas-json` version bump in universe
if: steps.filter.outputs.eas-json == 'true'
uses: benc-uk/workflow-dispatch@v1
with:
repo: expo/universe
ref: main
workflow: update-eas-json.yml
token: ${{ secrets.EXPO_BOT_PAT }}
+21
View File
@@ -8,6 +8,27 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Add --no-channel flag for update and rollback to embedded. ([#2339](https://github.com/expo/eas-cli/pull/2339) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
### 🧹 Chores
- Amend credential removal wording. ([#2334](https://github.com/expo/eas-cli/pull/2334) by [@quinlanj](https://github.com/quinlanj))
## [7.8.2](https://github.com/expo/eas-cli/releases/tag/v7.8.2) - 2024-04-15
### 🐛 Bug fixes
- Fix display of errors when expo-updates CLI command fails. ([#2324](https://github.com/expo/eas-cli/pull/2324) by [@wschurman](https://github.com/wschurman))
- Move credentials endpoints to paginated counterparts. ([#2327](https://github.com/expo/eas-cli/pull/2327) by [@quinlanj](https://github.com/quinlanj))
### 🧹 Chores
- Add progress bar for fetching paginated datasets. ([#2326](https://github.com/expo/eas-cli/pull/2326) by [@quinlanj](https://github.com/quinlanj))
## [7.8.1](https://github.com/expo/eas-cli/releases/tag/v7.8.1) - 2024-04-11
### 🐛 Bug fixes
- Fix command source files URLs in autogenerated `README`. ([#2318](https://github.com/expo/eas-cli/pull/2318) by [@szdziedzic](https://github.com/szdziedzic))
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"version": "7.8.1",
"version": "7.8.2",
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}
+59 -59
View File
@@ -137,7 +137,7 @@ ALIASES
$ eas login
```
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/account/login.ts)_
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -154,7 +154,7 @@ ALIASES
$ eas logout
```
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -171,7 +171,7 @@ ALIASES
$ eas whoami
```
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/account/view.ts)_
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -185,7 +185,7 @@ DESCRIPTION
display or change analytics settings
```
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/analytics.ts)_
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/analytics.ts)_
## `eas autocomplete [SHELL]`
@@ -237,7 +237,7 @@ DESCRIPTION
create a branch
```
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/branch/create.ts)_
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/branch/create.ts)_
## `eas branch:delete [NAME]`
@@ -258,7 +258,7 @@ DESCRIPTION
delete a branch
```
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/branch/delete.ts)_
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/branch/delete.ts)_
## `eas branch:list`
@@ -278,7 +278,7 @@ DESCRIPTION
list all branches
```
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/branch/list.ts)_
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/branch/list.ts)_
## `eas branch:rename`
@@ -298,7 +298,7 @@ DESCRIPTION
rename a branch
```
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/branch/rename.ts)_
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/branch/rename.ts)_
## `eas branch:view [NAME]`
@@ -321,7 +321,7 @@ DESCRIPTION
view a branch
```
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/branch/view.ts)_
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/branch/view.ts)_
## `eas build`
@@ -356,7 +356,7 @@ DESCRIPTION
start a build
```
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/index.ts)_
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -375,7 +375,7 @@ DESCRIPTION
cancel a build
```
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -392,7 +392,7 @@ DESCRIPTION
configure the project to support EAS Build
```
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:delete [BUILD_ID]`
@@ -411,7 +411,7 @@ DESCRIPTION
delete a build
```
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/delete.ts)_
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/delete.ts)_
## `eas build:inspect`
@@ -446,7 +446,7 @@ DESCRIPTION
inspect the state of the project at specific build stages, useful for troubleshooting
```
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/inspect.ts)_
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/inspect.ts)_
## `eas build:list`
@@ -487,7 +487,7 @@ DESCRIPTION
list all builds for your project
```
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/list.ts)_
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:resign`
@@ -513,7 +513,7 @@ DESCRIPTION
re-sign a build archive
```
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/resign.ts)_
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/resign.ts)_
## `eas build:run`
@@ -539,7 +539,7 @@ DESCRIPTION
run simulator/emulator builds from eas-cli
```
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/run.ts)_
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/run.ts)_
## `eas build:submit`
@@ -589,7 +589,7 @@ DESCRIPTION
get the latest version from EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/version/get.ts)_
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/version/get.ts)_
## `eas build:version:set`
@@ -608,7 +608,7 @@ DESCRIPTION
update version of an app
```
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/version/set.ts)_
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/version/set.ts)_
## `eas build:version:sync`
@@ -627,7 +627,7 @@ DESCRIPTION
update a version in native code with a value stored on EAS servers
```
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/version/sync.ts)_
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/version/sync.ts)_
## `eas build:view [BUILD_ID]`
@@ -644,7 +644,7 @@ DESCRIPTION
view a build for your project
```
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/build/view.ts)_
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/build/view.ts)_
## `eas channel:create [NAME]`
@@ -665,7 +665,7 @@ DESCRIPTION
create a channel
```
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/channel/create.ts)_
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/channel/create.ts)_
## `eas channel:edit [NAME]`
@@ -687,7 +687,7 @@ DESCRIPTION
point a channel at a new branch
```
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/channel/edit.ts)_
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/channel/edit.ts)_
## `eas channel:list`
@@ -707,7 +707,7 @@ DESCRIPTION
list all channels
```
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/channel/list.ts)_
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/channel/list.ts)_
## `eas channel:rollout [CHANNEL]`
@@ -739,7 +739,7 @@ DESCRIPTION
Roll a new branch out on a channel incrementally.
```
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/channel/rollout.ts)_
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/channel/rollout.ts)_
## `eas channel:view [NAME]`
@@ -762,7 +762,7 @@ DESCRIPTION
view a channel
```
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/channel/view.ts)_
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/channel/view.ts)_
## `eas config`
@@ -783,7 +783,7 @@ DESCRIPTION
display project configuration (app.json + eas.json)
```
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/config.ts)_
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/config.ts)_
## `eas credentials`
@@ -800,7 +800,7 @@ DESCRIPTION
manage credentials
```
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/credentials/index.ts)_
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/credentials/index.ts)_
## `eas credentials:configure-build`
@@ -818,7 +818,7 @@ DESCRIPTION
Set up credentials for building your project.
```
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/credentials/configure-build.ts)_
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/credentials/configure-build.ts)_
## `eas device:create`
@@ -832,7 +832,7 @@ DESCRIPTION
register new Apple Devices to use for internal distribution
```
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/device/create.ts)_
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:delete`
@@ -852,7 +852,7 @@ DESCRIPTION
remove a registered device from your account
```
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/device/delete.ts)_
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/device/delete.ts)_
## `eas device:list`
@@ -873,7 +873,7 @@ DESCRIPTION
list all registered devices for your account
```
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/device/list.ts)_
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:rename`
@@ -894,7 +894,7 @@ DESCRIPTION
rename a registered device
```
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/device/rename.ts)_
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/device/rename.ts)_
## `eas device:view [UDID]`
@@ -908,7 +908,7 @@ DESCRIPTION
view a device for your project
```
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/device/view.ts)_
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/device/view.ts)_
## `eas diagnostics`
@@ -922,7 +922,7 @@ DESCRIPTION
display environment info
```
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/diagnostics.ts)_
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/diagnostics.ts)_
## `eas help [COMMAND]`
@@ -1010,7 +1010,7 @@ DESCRIPTION
validate the local store configuration
```
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/metadata/lint.ts)_
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/metadata/lint.ts)_
## `eas metadata:pull`
@@ -1027,7 +1027,7 @@ DESCRIPTION
generate the local store configuration from the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/metadata/pull.ts)_
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/metadata/pull.ts)_
## `eas metadata:push`
@@ -1044,7 +1044,7 @@ DESCRIPTION
sync the local store configuration to the app stores
```
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/metadata/push.ts)_
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/metadata/push.ts)_
## `eas open`
@@ -1058,7 +1058,7 @@ DESCRIPTION
open the project page in a web browser
```
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/open.ts)_
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/open.ts)_
## `eas project:info`
@@ -1072,7 +1072,7 @@ DESCRIPTION
information about the current project
```
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/project/info.ts)_
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/project/info.ts)_
## `eas project:init`
@@ -1094,7 +1094,7 @@ ALIASES
$ eas init
```
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/project/init.ts)_
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/project/init.ts)_
## `eas secret:create`
@@ -1117,7 +1117,7 @@ DESCRIPTION
create an environment secret on the current project or owner account
```
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -1135,7 +1135,7 @@ DESCRIPTION
delete an environment secret by ID
```
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -1149,7 +1149,7 @@ DESCRIPTION
list environment secrets available for your current app
```
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/secret/list.ts)_
## `eas secret:push`
@@ -1169,7 +1169,7 @@ DESCRIPTION
read environment secrets from env file and store on the server
```
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/secret/push.ts)_
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/secret/push.ts)_
## `eas submit`
@@ -1200,7 +1200,7 @@ ALIASES
$ eas build:submit
```
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/submit.ts)_
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/submit.ts)_
## `eas update`
@@ -1233,7 +1233,7 @@ DESCRIPTION
publish an update group
```
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/index.ts)_
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/index.ts)_
## `eas update:configure`
@@ -1251,7 +1251,7 @@ DESCRIPTION
configure the project to support EAS Update
```
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/configure.ts)_
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/configure.ts)_
## `eas update:delete GROUPID`
@@ -1272,7 +1272,7 @@ DESCRIPTION
delete all the updates in an update group
```
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/delete.ts)_
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/delete.ts)_
## `eas update:list`
@@ -1294,7 +1294,7 @@ DESCRIPTION
view the recent updates
```
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/list.ts)_
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/list.ts)_
## `eas update:republish`
@@ -1321,7 +1321,7 @@ DESCRIPTION
roll back to an existing update
```
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/republish.ts)_
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/republish.ts)_
## `eas update:roll-back-to-embedded`
@@ -1348,7 +1348,7 @@ DESCRIPTION
roll back to the embedded update
```
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
## `eas update:rollback`
@@ -1367,7 +1367,7 @@ DESCRIPTION
roll back to an embedded update or an existing update
```
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/rollback.ts)_
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/rollback.ts)_
## `eas update:view GROUPID`
@@ -1387,7 +1387,7 @@ DESCRIPTION
update group details
```
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/update/view.ts)_
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/update/view.ts)_
## `eas webhook:create`
@@ -1408,7 +1408,7 @@ DESCRIPTION
create a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -1428,7 +1428,7 @@ DESCRIPTION
delete a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -1446,7 +1446,7 @@ DESCRIPTION
list webhooks
```
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -1468,7 +1468,7 @@ DESCRIPTION
update a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -1485,7 +1485,7 @@ DESCRIPTION
view a webhook
```
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v7.8.1/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v7.8.2/packages/eas-cli/src/commands/webhook/view.ts)_
## `eas whoami`
+146
View File
@@ -9470,6 +9470,22 @@
"isDeprecated": true,
"deprecationReason": "Classic updates have been deprecated."
},
{
"name": "pushNotifications",
"description": "App query field for querying details about an app's push notifications",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AppPushNotifications",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pushSecurityEnabled",
"description": null,
@@ -11320,6 +11336,109 @@
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AppPushNotifications",
"description": null,
"fields": [
{
"name": "id",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "insights",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "AppPushNotificationsInsights",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AppPushNotificationsInsights",
"description": null,
"fields": [
{
"name": "id",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "notificationsSentOverTime",
"description": null,
"args": [
{
"name": "timespan",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "InsightsTimespan",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "NotificationsSentOverTimeData",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "AppQuery",
@@ -30962,6 +31081,33 @@
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "NotificationsSentOverTimeData",
"description": null,
"fields": [
{
"name": "data",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "LineChartData",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Offer",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "7.8.1",
"version": "7.8.2",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
+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.97';
const PLUGIN_PACKAGE_VERSION = '1.0.100';
export enum LocalBuildMode {
/**
@@ -7,6 +7,7 @@ import { instance, mock } from 'ts-mockito';
import UpdatePublish from '..';
import { ensureBranchExistsAsync } from '../../../branch/queries';
import { ensureChannelExistsAsync } from '../../../channel/queries';
import {
DynamicPrivateProjectConfigContextField,
DynamicPublicProjectConfigContextField,
@@ -45,6 +46,7 @@ jest.mock('fs');
jest.mock('@expo/config');
jest.mock('@expo/config-plugins');
jest.mock('../../../branch/queries');
jest.mock('../../../channel/queries');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../update/configure');
jest.mock('../../../update/getBranchNameFromChannelNameAsync');
@@ -94,6 +96,16 @@ describe(UpdatePublish.name, () => {
);
});
it('errors with both --channel and --no-channel', async () => {
const flags = ['--channel=channel123', '--no-channel'];
mockTestProject();
await expect(new UpdatePublish(flags, commandOptions).run()).rejects.toThrow(
'Cannot use --channel with --no-channel'
);
});
it('creates a new update with --non-interactive, --branch, and --message', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc'];
@@ -147,6 +159,31 @@ describe(UpdatePublish.name, () => {
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
it('creates a new update with --no-channel', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc', '--no-channel'];
const { platforms, runtimeVersion } = mockTestExport();
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: true,
});
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue(
platforms.map(platform => ({
...updateStub,
runtimeVersion,
platform,
}))
);
await new UpdatePublish(flags, commandOptions).run();
expect(ensureChannelExistsAsync).not.toHaveBeenCalled();
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
it('creates a new update with the public expo config', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc'];
@@ -6,6 +6,7 @@ import path from 'path';
import { instance, mock } from 'ts-mockito';
import { ensureBranchExistsAsync } from '../../../branch/queries';
import { ensureChannelExistsAsync } from '../../../channel/queries';
import {
DynamicPrivateProjectConfigContextField,
DynamicPublicProjectConfigContextField,
@@ -44,6 +45,7 @@ jest.mock('fs');
jest.mock('@expo/config');
jest.mock('@expo/config-plugins');
jest.mock('../../../branch/queries');
jest.mock('../../../channel/queries');
jest.mock('../../../commandUtils/context/contextUtils/getProjectIdAsync');
jest.mock('../../../project/projectUtils', () => ({
...jest.requireActual('../../../project/projectUtils'),
@@ -80,6 +82,16 @@ describe(UpdateRollBackToEmbedded.name, () => {
);
});
it('errors with both --channel and --no-channel', async () => {
const flags = ['--channel=channel123', '--no-channel'];
mockTestProject();
await expect(new UpdateRollBackToEmbedded(flags, commandOptions).run()).rejects.toThrow(
'Cannot use --channel with --no-channel'
);
});
it('creates a roll back to embedded with --non-interactive, --branch, and --message', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc'];
@@ -137,6 +149,42 @@ describe(UpdateRollBackToEmbedded.name, () => {
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
it('creates a roll back to embedded with --no-channel', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc', '--no-channel'];
const { projectId } = mockTestProject();
const platforms = ['android', 'ios'];
const runtimeVersion = 'exposdk:47.0.0';
jest.mocked(Updates.getRuntimeVersionAsync).mockResolvedValue(runtimeVersion);
jest.mocked(getBranchNameFromChannelNameAsync).mockResolvedValue('branchFromChannel');
jest.mocked(ensureBranchExistsAsync).mockResolvedValue({
branchId: 'branch123',
createdBranch: true,
});
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockResolvedValue(
platforms.map(platform => ({
...updateStub,
runtimeVersion,
platform,
}))
);
await new UpdateRollBackToEmbedded(flags, commandOptions).run();
expect(ensureChannelExistsAsync).not.toHaveBeenCalled();
expect(ensureBranchExistsAsync).toHaveBeenCalledWith(
expect.any(Object), // graphql client
{
appId: projectId,
branchName: 'branchFromChannel',
}
);
expect(PublishMutation.publishUpdateGroupAsync).toHaveBeenCalled();
});
it('creates a roll back to embedded with the public expo config', async () => {
const flags = ['--non-interactive', '--branch=branch123', '--message=abc'];
+13 -1
View File
@@ -64,6 +64,7 @@ type RawUpdateFlags = {
'skip-bundler': boolean;
'clear-cache': boolean;
'private-key-path'?: string;
'no-channel': boolean;
'non-interactive': boolean;
json: boolean;
/** @deprecated see UpdateRepublish command */
@@ -81,6 +82,7 @@ type UpdateFlags = {
inputDir: string;
skipBundler: boolean;
clearCache: boolean;
noChannel: boolean;
privateKeyPath?: string;
json: boolean;
nonInteractive: boolean;
@@ -143,6 +145,10 @@ export default class UpdatePublish extends EasCommand {
description: `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 certificate's directory.`,
required: false,
}),
'no-channel': Flags.boolean({
description: `Skip EAS channel creation.`,
default: false,
}),
...EasNonInteractiveAndJsonFlags,
};
@@ -164,6 +170,7 @@ export default class UpdatePublish extends EasCommand {
skipBundler,
clearCache,
privateKeyPath,
noChannel: noChannelFlag,
json: jsonFlag,
nonInteractive,
branchName: branchNameArg,
@@ -372,7 +379,7 @@ export default class UpdatePublish extends EasCommand {
appId: projectId,
branchName,
});
if (createdBranch) {
if (createdBranch && !noChannelFlag) {
await ensureChannelExistsAsync(graphqlClient, {
appId: projectId,
branchId,
@@ -548,6 +555,10 @@ export default class UpdatePublish extends EasCommand {
);
}
if (channelName && flags['no-channel']) {
Errors.error('Cannot use --channel with --no-channel', { exit: 1 });
}
if (flags.group || flags.republish) {
// Pick the first flag set that is defined, in this specific order
const args = [
@@ -575,6 +586,7 @@ export default class UpdatePublish extends EasCommand {
clearCache: flags['clear-cache'],
platform: flags.platform as RequestedPlatform,
privateKeyPath: flags['private-key-path'],
noChannel: flags['no-channel'],
nonInteractive,
json: flags.json ?? false,
};
@@ -54,6 +54,7 @@ type RawUpdateFlags = {
message?: string;
platform: string;
'private-key-path'?: string;
'no-channel': boolean;
'non-interactive': boolean;
json: boolean;
};
@@ -65,6 +66,7 @@ type UpdateFlags = {
channelName?: string;
updateMessage?: string;
privateKeyPath?: string;
noChannel: boolean;
json: boolean;
nonInteractive: boolean;
};
@@ -104,6 +106,10 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
description: `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 certificate's directory.`,
required: false,
}),
'no-channel': Flags.boolean({
description: `Skip EAS channel creation.`,
default: false,
}),
...EasNonInteractiveAndJsonFlags,
};
@@ -122,6 +128,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
channelName: channelNameArg,
updateMessage: updateMessageArg,
privateKeyPath,
noChannel: noChannelFlag,
json: jsonFlag,
nonInteractive,
branchName: branchNameArg,
@@ -188,16 +195,17 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
appId: projectId,
branchName,
});
if (createdBranch) {
if (createdBranch && !noChannelFlag) {
await ensureChannelExistsAsync(graphqlClient, {
appId: projectId,
branchId,
channelName: branchName,
});
Log.withTick(
`Channel: ${chalk.bold(branchName)} pointed at branch: ${chalk.bold(branchName)}`
);
}
Log.withTick(`Channel: ${chalk.bold(branchName)} pointed at branch: ${chalk.bold(branchName)}`);
const gitCommitHash = await vcsClient.getCommitHashAsync();
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
@@ -387,6 +395,10 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
);
}
if (channelName && flags['no-channel']) {
Errors.error('Cannot use --channel with --no-channel', { exit: 1 });
}
return {
auto,
branchName,
@@ -394,6 +406,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
updateMessage,
platform: flags.platform as RequestedPlatform,
privateKeyPath: flags['private-key-path'],
noChannel: flags['no-channel'],
nonInteractive,
json: flags.json ?? false,
};
@@ -4,27 +4,76 @@ import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../../../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import {
GoogleServiceAccountKeyByAccountQuery,
GoogleServiceAccountKeyFragment,
GoogleServiceAccountKeysPaginatedByAccountQuery,
} from '../../../../../graphql/generated';
import { GoogleServiceAccountKeyFragmentNode } from '../../../../../graphql/types/credentials/GoogleServiceAccountKey';
import { Connection, QueryParams, fetchEntireDatasetAsync } from '../../../../../utils/relay';
export const GoogleServiceAccountKeyQuery = {
async getAllForAccountAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string
): Promise<GoogleServiceAccountKeyFragment[]> {
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<GoogleServiceAccountKeyFragment>> => {
return await GoogleServiceAccountKeyQuery.getAllForAccountPaginatedAsync(
graphqlClient,
accountName,
relayArgs
);
};
return await fetchEntireDatasetAsync({
paginatedGetterAsync,
progressBarLabel: 'fetching Google Service Account Keys...',
});
},
async getAllForAccountPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string,
{
after,
first,
before,
last,
}: { after?: string; first?: number; before?: string; last?: number }
): Promise<
GoogleServiceAccountKeysPaginatedByAccountQuery['account']['byName']['googleServiceAccountKeysPaginated']
> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<GoogleServiceAccountKeyByAccountQuery>(
.query<GoogleServiceAccountKeysPaginatedByAccountQuery>(
gql`
query GoogleServiceAccountKeyByAccountQuery($accountName: String!) {
query GoogleServiceAccountKeysPaginatedByAccountQuery(
$accountName: String!
$after: String
$first: Int
$before: String
$last: Int
) {
account {
byName(accountName: $accountName) {
id
googleServiceAccountKeys {
id
...GoogleServiceAccountKeyFragment
googleServiceAccountKeysPaginated(
after: $after
first: $first
before: $before
last: $last
) {
edges {
cursor
node {
id
...GoogleServiceAccountKeyFragment
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
@@ -33,6 +82,10 @@ export const GoogleServiceAccountKeyQuery = {
`,
{
accountName,
after,
first,
before,
last,
},
{
additionalTypenames: ['GoogleServiceAccountKey'],
@@ -40,6 +93,6 @@ export const GoogleServiceAccountKeyQuery = {
)
.toPromise()
);
return data.account.byName.googleServiceAccountKeys;
return data.account.byName.googleServiceAccountKeysPaginated;
},
};
@@ -48,8 +48,13 @@ export function formatDistributionCertificate(
buildCredentials => buildCredentials.iosAppCredentials.app
);
if (apps.length) {
const appFullNames = apps.map(app => app.fullName).join(',');
line += chalk.gray(`\n 📲 Used by: ${appFullNames}`);
// iosAppBuildCredentialsList is capped at 20 on www
const appFullNames = apps
.map(app => app.fullName)
.slice(0, 19)
.join(',');
const andMaybeMore = apps.length > 19 ? ' (and more)' : '';
line += chalk.gray(`\n 📲 Used by: ${appFullNames}${andMaybeMore}`);
}
if (validSerialNumbers?.includes(serialNumber)) {
@@ -185,8 +185,13 @@ export function formatPushKey(
const apps = pushKey.iosAppCredentialsList.map(appCredentials => appCredentials.app);
if (apps.length) {
const appFullNames = apps.map(app => app.fullName).join(',');
line += chalk.gray(`\n 📲 Used by: ${appFullNames}`);
// iosAppCredentialsList is capped at 20 on www
const appFullNames = apps
.map(app => app.fullName)
.slice(0, 19)
.join(',');
const andMaybeMore = apps.length > 19 ? ' (and more)' : '';
line += chalk.gray(`\n 📲 Used by: ${appFullNames}${andMaybeMore}`);
}
if (validPushKeyIdentifiers?.includes(keyIdentifier)) {
@@ -34,14 +34,20 @@ export class RemoveDistributionCertificate {
buildCredentials => buildCredentials.iosAppCredentials.app
);
if (apps.length !== 0) {
const appFullNames = apps.map(app => app.fullName).join(',');
// iosAppBuildCredentialsList is capped at 20 on www
const appFullNames = apps
.map(app => app.fullName)
.slice(0, 19)
.join(',');
const andMaybeMore = apps.length > 19 ? ' (and more)' : '';
if (ctx.nonInteractive) {
throw new Error(
`Certificate is currently used by ${appFullNames} and cannot be deleted in non-interactive mode.`
`Certificate is currently used by ${appFullNames}${andMaybeMore} and cannot be deleted in non-interactive mode.`
);
}
const confirm = await confirmAsync({
message: `You are removing certificate used by ${appFullNames}. Do you want to continue?`,
message: `You are removing certificate used by ${appFullNames}${andMaybeMore}. Do you want to continue?`,
});
if (!confirm) {
Log.log('Aborting');
@@ -27,9 +27,14 @@ export class RemovePushKey {
const apps = this.pushKey.iosAppCredentialsList.map(appCredentials => appCredentials.app);
if (apps.length !== 0) {
const appFullNames = apps.map(app => app.fullName).join(',');
// iosAppCredentialsList is capped at 20 on www
const appFullNames = apps
.map(app => app.fullName)
.slice(0, 19)
.join(',');
const andMaybeMore = apps.length > 19 ? ' (and more)' : '';
const confirm = await confirmAsync({
message: `Removing this push key will disable push notifications for ${appFullNames}. Do you want to continue?`,
message: `Removing this push key will disable push notifications for ${appFullNames}${andMaybeMore}. Do you want to continue?`,
});
if (!confirm) {
Log.log('Aborting');
@@ -326,7 +326,7 @@ export async function getDevicesForAppleTeamAsync(
): Promise<AppleDeviceFragment[]> {
return await AppleDeviceQuery.getAllByAppleTeamIdentifierAsync(
graphqlClient,
account.id,
account.name,
appleTeamIdentifier,
{
useCache,
@@ -4,27 +4,76 @@ import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../../../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import {
AppStoreConnectApiKeyByAccountQuery,
AppStoreConnectApiKeyFragment,
AppStoreConnectApiKeysPaginatedByAccountQuery,
} from '../../../../../graphql/generated';
import { AppStoreConnectApiKeyFragmentNode } from '../../../../../graphql/types/credentials/AppStoreConnectApiKey';
import { Connection, QueryParams, fetchEntireDatasetAsync } from '../../../../../utils/relay';
export const AppStoreConnectApiKeyQuery = {
async getAllForAccountAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string
): Promise<AppStoreConnectApiKeyFragment[]> {
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<AppStoreConnectApiKeyFragment>> => {
return await AppStoreConnectApiKeyQuery.getAllForAccountPaginatedAsync(
graphqlClient,
accountName,
relayArgs
);
};
return await fetchEntireDatasetAsync({
paginatedGetterAsync,
progressBarLabel: 'fetching ASC Keys...',
});
},
async getAllForAccountPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string,
{
after,
first,
before,
last,
}: { after?: string; first?: number; before?: string; last?: number }
): Promise<
AppStoreConnectApiKeysPaginatedByAccountQuery['account']['byName']['appStoreConnectApiKeysPaginated']
> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<AppStoreConnectApiKeyByAccountQuery>(
.query<AppStoreConnectApiKeysPaginatedByAccountQuery>(
gql`
query AppStoreConnectApiKeyByAccountQuery($accountName: String!) {
query AppStoreConnectApiKeysPaginatedByAccountQuery(
$accountName: String!
$after: String
$first: Int
$before: String
$last: Int
) {
account {
byName(accountName: $accountName) {
id
appStoreConnectApiKeys {
id
...AppStoreConnectApiKeyFragment
appStoreConnectApiKeysPaginated(
after: $after
first: $first
before: $before
last: $last
) {
edges {
cursor
node {
id
...AppStoreConnectApiKeyFragment
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
@@ -33,6 +82,10 @@ export const AppStoreConnectApiKeyQuery = {
`,
{
accountName,
after,
first,
before,
last,
},
{
additionalTypenames: ['AppStoreConnectApiKey'],
@@ -40,6 +93,6 @@ export const AppStoreConnectApiKeyQuery = {
)
.toPromise()
);
return data.account.byName.appStoreConnectApiKeys;
return data.account.byName.appStoreConnectApiKeysPaginated;
},
};
@@ -1,4 +1,3 @@
import assert from 'assert';
import { print } from 'graphql';
import gql from 'graphql-tag';
@@ -7,15 +6,16 @@ import { DeviceNotFoundError } from '../../../../../devices/utils/errors';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import {
AppleDevice,
AppleDeviceFilterInput,
AppleDeviceFragment,
AppleDevicesByAppleTeamQuery,
AppleDevicesByIdentifierQuery,
AppleDevicesByTeamIdentifierQuery,
AppleDevicesByTeamIdentifierQueryVariables,
AppleDevicesPaginatedByAccountQuery,
AppleTeamFragment,
} from '../../../../../graphql/generated';
import { AppleDeviceFragmentNode } from '../../../../../graphql/types/credentials/AppleDevice';
import { AppleTeamFragmentNode } from '../../../../../graphql/types/credentials/AppleTeam';
import { Connection, QueryParams, fetchEntireDatasetAsync } from '../../../../../utils/relay';
import { formatAppleTeam } from '../../../actions/AppleTeamFormatting';
export type AppleDeviceFragmentWithAppleTeam = AppleDeviceFragment & {
@@ -38,51 +38,25 @@ export type AppleDevicesByIdentifierQueryResult = AppleDeviceQueryResult & {
export const AppleDeviceQuery = {
async getAllByAppleTeamIdentifierAsync(
graphqlClient: ExpoGraphqlClient,
accountId: string,
accountName: string,
appleTeamIdentifier: string,
{ useCache = true }: { useCache?: boolean } = {}
): Promise<AppleDeviceFragmentWithAppleTeam[]> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<AppleDevicesByAppleTeamQuery>(
gql`
query AppleDevicesByAppleTeamQuery($accountId: ID!, $appleTeamIdentifier: String!) {
appleTeam {
byAppleTeamIdentifier(accountId: $accountId, identifier: $appleTeamIdentifier) {
id
...AppleTeamFragment
appleDevices {
id
...AppleDeviceFragment
appleTeam {
id
...AppleTeamFragment
}
}
}
}
}
${print(AppleTeamFragmentNode)}
${print(AppleDeviceFragmentNode)}
`,
{
accountId,
appleTeamIdentifier,
},
{
additionalTypenames: ['AppleDevice'],
requestPolicy: useCache ? 'cache-first' : 'network-only',
}
)
.toPromise()
);
assert(
data.appleTeam.byAppleTeamIdentifier,
'byAppleTeamIdentifier should be defined in this context - enforced by GraphQL'
);
const { appleDevices } = data.appleTeam.byAppleTeamIdentifier;
assert(appleDevices, 'Apple Devices should be defined in this context - enforced by GraphQL');
return appleDevices;
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<AppleDeviceFragmentWithAppleTeam>> => {
return await AppleDeviceQuery.getAllForAccountPaginatedAsync(graphqlClient, accountName, {
...relayArgs,
filter: {
appleTeamIdentifier,
},
useCache,
});
};
return await fetchEntireDatasetAsync({
paginatedGetterAsync,
progressBarLabel: 'Fetching Apple devices...',
});
},
async getAllForAppleTeamAsync(
@@ -139,41 +113,21 @@ export const AppleDeviceQuery = {
graphqlClient: ExpoGraphqlClient,
accountName: string,
identifier: string
): Promise<AppleDevicesByIdentifierQueryResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<AppleDevicesByIdentifierQuery>(
gql`
query AppleDevicesByIdentifier($accountName: String!, $identifier: String!) {
account {
byName(accountName: $accountName) {
id
appleDevices(identifier: $identifier) {
id
model
identifier
name
deviceClass
enabled
appleTeam {
id
appleTeamIdentifier
appleTeamName
}
}
}
}
}
`,
{ accountName, identifier },
{
additionalTypenames: ['AppleDevice', 'AppleTeam'],
}
)
.toPromise()
);
const device = data.account.byName.appleDevices[0];
): Promise<AppleDeviceFragmentWithAppleTeam> {
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<AppleDeviceFragmentWithAppleTeam>> => {
return await AppleDeviceQuery.getAllForAccountPaginatedAsync(graphqlClient, accountName, {
...relayArgs,
filter: {
identifier,
},
});
};
const devices = await fetchEntireDatasetAsync({
paginatedGetterAsync,
});
const device = devices[0];
if (!device) {
throw new DeviceNotFoundError(
`Device with id ${identifier} was not found on account ${accountName}.`
@@ -181,4 +135,86 @@ export const AppleDeviceQuery = {
}
return device;
},
async getAllForAccountPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string,
{
after,
first,
before,
last,
filter,
useCache = true,
}: {
after?: string;
first?: number;
before?: string;
last?: number;
filter?: AppleDeviceFilterInput;
useCache?: boolean;
}
): Promise<AppleDevicesPaginatedByAccountQuery['account']['byName']['appleDevicesPaginated']> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<AppleDevicesPaginatedByAccountQuery>(
gql`
query AppleDevicesPaginatedByAccountQuery(
$accountName: String!
$after: String
$first: Int
$before: String
$last: Int
$filter: AppleDeviceFilterInput
) {
account {
byName(accountName: $accountName) {
id
appleDevicesPaginated(
after: $after
first: $first
before: $before
last: $last
filter: $filter
) {
edges {
cursor
node {
id
...AppleDeviceFragment
appleTeam {
id
...AppleTeamFragment
}
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
}
${print(AppleTeamFragmentNode)}
${print(AppleDeviceFragmentNode)}
`,
{
accountName,
after,
first,
before,
last,
filter,
},
{
additionalTypenames: ['AppleDevice'],
requestPolicy: useCache ? 'cache-first' : 'network-only',
}
)
.toPromise()
);
return data.account.byName.appleDevicesPaginated;
},
};
@@ -5,13 +5,14 @@ import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../../../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import {
AppleDistributionCertificateByAccountQuery,
AppleDistributionCertificateByAppQuery,
AppleDistributionCertificateFragment,
AppleDistributionCertificatesPaginatedByAccountQuery,
IosDistributionType,
} from '../../../../../graphql/generated';
import { AppleDistributionCertificateFragmentNode } from '../../../../../graphql/types/credentials/AppleDistributionCertificate';
import { AppleTeamFragmentNode } from '../../../../../graphql/types/credentials/AppleTeam';
import { Connection, QueryParams, fetchEntireDatasetAsync } from '../../../../../utils/relay';
export const AppleDistributionCertificateQuery = {
async getForAppAsync(
@@ -81,17 +82,65 @@ export const AppleDistributionCertificateQuery = {
graphqlClient: ExpoGraphqlClient,
accountName: string
): Promise<AppleDistributionCertificateFragment[]> {
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<AppleDistributionCertificateFragment>> => {
return await AppleDistributionCertificateQuery.getAllForAccountPaginatedAsync(
graphqlClient,
accountName,
relayArgs
);
};
return await fetchEntireDatasetAsync({
paginatedGetterAsync,
progressBarLabel: 'fetching Apple Distribution Certificates...',
});
},
async getAllForAccountPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string,
{
after,
first,
before,
last,
}: { after?: string; first?: number; before?: string; last?: number }
): Promise<
AppleDistributionCertificatesPaginatedByAccountQuery['account']['byName']['appleDistributionCertificatesPaginated']
> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<AppleDistributionCertificateByAccountQuery>(
.query<AppleDistributionCertificatesPaginatedByAccountQuery>(
gql`
query AppleDistributionCertificateByAccountQuery($accountName: String!) {
query AppleDistributionCertificatesPaginatedByAccountQuery(
$accountName: String!
$after: String
$first: Int
$before: String
$last: Int
) {
account {
byName(accountName: $accountName) {
id
appleDistributionCertificates {
id
...AppleDistributionCertificateFragment
appleDistributionCertificatesPaginated(
after: $after
first: $first
before: $before
last: $last
) {
edges {
cursor
node {
id
...AppleDistributionCertificateFragment
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
@@ -100,6 +149,10 @@ export const AppleDistributionCertificateQuery = {
`,
{
accountName,
after,
first,
before,
last,
},
{
additionalTypenames: ['AppleDistributionCertificate'],
@@ -107,6 +160,6 @@ export const AppleDistributionCertificateQuery = {
)
.toPromise()
);
return data.account.byName.appleDistributionCertificates;
return data.account.byName.appleDistributionCertificatesPaginated;
},
};
@@ -3,25 +3,75 @@ import gql from 'graphql-tag';
import { ExpoGraphqlClient } from '../../../../../commandUtils/context/contextUtils/createGraphqlClient';
import { withErrorHandlingAsync } from '../../../../../graphql/client';
import { ApplePushKeyByAccountQuery, ApplePushKeyFragment } from '../../../../../graphql/generated';
import {
ApplePushKeyFragment,
ApplePushKeysPaginatedByAccountQuery,
} from '../../../../../graphql/generated';
import { ApplePushKeyFragmentNode } from '../../../../../graphql/types/credentials/ApplePushKey';
import { Connection, QueryParams, fetchEntireDatasetAsync } from '../../../../../utils/relay';
export const ApplePushKeyQuery = {
async getAllForAccountAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string
): Promise<ApplePushKeyFragment[]> {
const paginatedGetterAsync = async (
relayArgs: QueryParams
): Promise<Connection<ApplePushKeyFragment>> => {
return await ApplePushKeyQuery.getAllForAccountPaginatedAsync(
graphqlClient,
accountName,
relayArgs
);
};
return await fetchEntireDatasetAsync({
paginatedGetterAsync,
progressBarLabel: 'fetching Apple Push Keys...',
});
},
async getAllForAccountPaginatedAsync(
graphqlClient: ExpoGraphqlClient,
accountName: string,
{
after,
first,
before,
last,
}: { after?: string; first?: number; before?: string; last?: number }
): Promise<ApplePushKeysPaginatedByAccountQuery['account']['byName']['applePushKeysPaginated']> {
const data = await withErrorHandlingAsync(
graphqlClient
.query<ApplePushKeyByAccountQuery>(
.query<ApplePushKeysPaginatedByAccountQuery>(
gql`
query ApplePushKeyByAccountQuery($accountName: String!) {
query ApplePushKeysPaginatedByAccountQuery(
$accountName: String!
$after: String
$first: Int
$before: String
$last: Int
) {
account {
byName(accountName: $accountName) {
id
applePushKeys {
id
...ApplePushKeyFragment
applePushKeysPaginated(
after: $after
first: $first
before: $before
last: $last
) {
edges {
cursor
node {
id
...ApplePushKeyFragment
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}
}
@@ -30,6 +80,10 @@ export const ApplePushKeyQuery = {
`,
{
accountName,
after,
first,
before,
last,
},
{
additionalTypenames: ['ApplePushKey'],
@@ -37,6 +91,6 @@ export const ApplePushKeyQuery = {
)
.toPromise()
);
return data.account.byName.applePushKeys;
return data.account.byName.applePushKeysPaginated;
},
};
@@ -34,7 +34,7 @@ export default class DeviceCreateAction {
await runDeveloperPortalMethodAsync(
this.graphqlClient,
this.appStoreApi,
this.account.id,
this.account,
this.appleTeam
);
} else if (method === RegistrationMethod.INPUT) {
@@ -9,7 +9,7 @@ import {
import AppStoreApi from '../../../credentials/ios/appstore/AppStoreApi';
import { getRequestContext } from '../../../credentials/ios/appstore/authenticate';
import { AuthCtx } from '../../../credentials/ios/appstore/authenticateTypes';
import { AppleDeviceClass, AppleTeam } from '../../../graphql/generated';
import { AccountFragment, AppleDeviceClass, AppleTeam } from '../../../graphql/generated';
import Log from '../../../log';
import { ora } from '../../../ora';
import { promptAsync } from '../../../prompts';
@@ -25,14 +25,14 @@ const DEVICE_CLASS_TO_GRAPHQL_TYPE: Partial<Record<DeviceClass, AppleDeviceClass
export async function runDeveloperPortalMethodAsync(
graphqlClient: ExpoGraphqlClient,
appStoreApi: AppStoreApi,
accountId: string,
account: AccountFragment,
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
): Promise<void> {
const appleAuthCtx = await appStoreApi.ensureAuthenticatedAsync();
const unregisteredPortalDevices = await findUnregisteredPortalDevicesAsync(
graphqlClient,
appleAuthCtx,
accountId,
account.name,
appleTeam
);
if (unregisteredPortalDevices.length === 0) {
@@ -40,7 +40,7 @@ export async function runDeveloperPortalMethodAsync(
return;
}
const devicesToImport = await chooseDevicesToImportAsync(unregisteredPortalDevices);
await importDevicesAsync(graphqlClient, accountId, appleTeam, devicesToImport);
await importDevicesAsync(graphqlClient, account.id, appleTeam, devicesToImport);
}
async function importDevicesAsync(
@@ -88,12 +88,12 @@ async function importDeviceChunkAsync(
async function findUnregisteredPortalDevicesAsync(
graphqlClient: ExpoGraphqlClient,
appleAuthCtx: AuthCtx,
accountId: string,
accountName: string,
appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
): Promise<Device[]> {
const expoRegisteredDevices = await AppleDeviceQuery.getAllByAppleTeamIdentifierAsync(
graphqlClient,
accountId,
accountName,
appleTeam.appleTeamIdentifier,
{ useCache: false }
);
+60 -17
View File
@@ -1326,6 +1326,8 @@ export type App = Project & {
* @deprecated Classic updates have been deprecated.
*/
published: Scalars['Boolean']['output'];
/** App query field for querying details about an app's push notifications */
pushNotifications: AppPushNotifications;
pushSecurityEnabled: Scalars['Boolean']['output'];
/**
* Classic update release channel names (to be removed)
@@ -1740,6 +1742,23 @@ export enum AppPrivacy {
Unlisted = 'UNLISTED'
}
export type AppPushNotifications = {
__typename?: 'AppPushNotifications';
id: Scalars['ID']['output'];
insights: AppPushNotificationsInsights;
};
export type AppPushNotificationsInsights = {
__typename?: 'AppPushNotificationsInsights';
id: Scalars['ID']['output'];
notificationsSentOverTime: NotificationsSentOverTimeData;
};
export type AppPushNotificationsInsightsNotificationsSentOverTimeArgs = {
timespan: InsightsTimespan;
};
export type AppQuery = {
__typename?: 'AppQuery';
/**
@@ -4503,6 +4522,11 @@ export enum NotificationType {
Web = 'WEB'
}
export type NotificationsSentOverTimeData = {
__typename?: 'NotificationsSentOverTimeData';
data: LineChartData;
};
export type Offer = {
__typename?: 'Offer';
features?: Maybe<Array<Maybe<Feature>>>;
@@ -6571,6 +6595,17 @@ export type GoogleServiceAccountKeyByAccountQueryVariables = Exact<{
export type GoogleServiceAccountKeyByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, googleServiceAccountKeys: Array<{ __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any }> } } };
export type GoogleServiceAccountKeysPaginatedByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
after?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
}>;
export type GoogleServiceAccountKeysPaginatedByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, googleServiceAccountKeysPaginated: { __typename?: 'AccountGoogleServiceAccountKeysConnection', edges: Array<{ __typename?: 'AccountGoogleServiceAccountKeysEdge', cursor: string, node: { __typename?: 'GoogleServiceAccountKey', id: string, projectIdentifier: string, privateKeyIdentifier: string, clientEmail: string, clientIdentifier: string, createdAt: any, updatedAt: any } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type CreateAppStoreConnectApiKeyMutationVariables = Exact<{
appStoreConnectApiKeyInput: AppStoreConnectApiKeyInput;
accountId: Scalars['ID']['input'];
@@ -6736,12 +6771,16 @@ export type SetAppStoreConnectApiKeyForSubmissionsMutationVariables = Exact<{
export type SetAppStoreConnectApiKeyForSubmissionsMutation = { __typename?: 'RootMutation', iosAppCredentials: { __typename?: 'IosAppCredentialsMutation', setAppStoreConnectApiKeyForSubmissions: { __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosDistributionType: IosDistributionType, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any }> } | null }>, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }, pushKey?: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } | null, appStoreConnectApiKeyForSubmissions?: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } | null } } };
export type AppStoreConnectApiKeyByAccountQueryVariables = Exact<{
export type AppStoreConnectApiKeysPaginatedByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
after?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
}>;
export type AppStoreConnectApiKeyByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appStoreConnectApiKeys: Array<{ __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null }> } } };
export type AppStoreConnectApiKeysPaginatedByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appStoreConnectApiKeysPaginated: { __typename?: 'AccountAppStoreConnectApiKeysConnection', edges: Array<{ __typename?: 'AccountAppStoreConnectApiKeysEdge', cursor: string, node: { __typename?: 'AppStoreConnectApiKey', id: string, issuerIdentifier: string, keyIdentifier: string, name?: string | null, roles?: Array<AppStoreConnectUserRole> | null, createdAt: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type AppleAppIdentifierByBundleIdQueryVariables = Exact<{
accountName: Scalars['String']['input'];
@@ -6751,14 +6790,6 @@ export type AppleAppIdentifierByBundleIdQueryVariables = Exact<{
export type AppleAppIdentifierByBundleIdQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleAppIdentifiers: Array<{ __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string }> } } };
export type AppleDevicesByAppleTeamQueryVariables = Exact<{
accountId: Scalars['ID']['input'];
appleTeamIdentifier: Scalars['String']['input'];
}>;
export type AppleDevicesByAppleTeamQuery = { __typename?: 'RootQuery', appleTeam: { __typename?: 'AppleTeamQuery', byAppleTeamIdentifier?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any, appleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } }> } | null } };
export type AppleDevicesByTeamIdentifierQueryVariables = Exact<{
accountName: Scalars['String']['input'];
appleTeamIdentifier: Scalars['String']['input'];
@@ -6769,13 +6800,17 @@ export type AppleDevicesByTeamIdentifierQueryVariables = Exact<{
export type AppleDevicesByTeamIdentifierQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleTeams: Array<{ __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, deviceClass?: AppleDeviceClass | null, enabled?: boolean | null, model?: string | null, createdAt: any }> }> } } };
export type AppleDevicesByIdentifierQueryVariables = Exact<{
export type AppleDevicesPaginatedByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
identifier: Scalars['String']['input'];
after?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
filter?: InputMaybe<AppleDeviceFilterInput>;
}>;
export type AppleDevicesByIdentifierQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, model?: string | null, identifier: string, name?: string | null, deviceClass?: AppleDeviceClass | null, enabled?: boolean | null, appleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } }> } } };
export type AppleDevicesPaginatedByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDevicesPaginated: { __typename?: 'AccountAppleDevicesConnection', edges: Array<{ __typename?: 'AccountAppleDevicesEdge', cursor: string, node: { __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any, appleTeam: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type AppleDistributionCertificateByAppQueryVariables = Exact<{
projectFullName: Scalars['String']['input'];
@@ -6786,12 +6821,16 @@ export type AppleDistributionCertificateByAppQueryVariables = Exact<{
export type AppleDistributionCertificateByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, distributionCertificate?: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } | null }> }> } } };
export type AppleDistributionCertificateByAccountQueryVariables = Exact<{
export type AppleDistributionCertificatesPaginatedByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
after?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
}>;
export type AppleDistributionCertificateByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDistributionCertificates: Array<{ __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> }> } } };
export type AppleDistributionCertificatesPaginatedByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, appleDistributionCertificatesPaginated: { __typename?: 'AccountAppleDistributionCertificatesConnection', edges: Array<{ __typename?: 'AccountAppleDistributionCertificatesEdge', cursor: string, node: { __typename?: 'AppleDistributionCertificate', id: string, certificateP12?: string | null, certificatePassword?: string | null, serialNumber: string, developerPortalIdentifier?: string | null, validityNotBefore: any, validityNotAfter: any, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, iosAppCredentials: { __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, developerPortalIdentifier?: string | null } | null }> } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type AppleProvisioningProfilesByAppQueryVariables = Exact<{
projectFullName: Scalars['String']['input'];
@@ -6802,12 +6841,16 @@ export type AppleProvisioningProfilesByAppQueryVariables = Exact<{
export type AppleProvisioningProfilesByAppQuery = { __typename?: 'RootQuery', app: { __typename?: 'AppQuery', byFullName: { __typename?: 'App', id: string, iosAppCredentials: Array<{ __typename?: 'IosAppCredentials', id: string, iosAppBuildCredentialsList: Array<{ __typename?: 'IosAppBuildCredentials', id: string, provisioningProfile?: { __typename?: 'AppleProvisioningProfile', id: string, expiration: any, developerPortalIdentifier?: string | null, provisioningProfile?: string | null, updatedAt: any, status: string, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, appleDevices: Array<{ __typename?: 'AppleDevice', id: string, identifier: string, name?: string | null, model?: string | null, deviceClass?: AppleDeviceClass | null, createdAt: any }>, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } } | null }> }> } } };
export type ApplePushKeyByAccountQueryVariables = Exact<{
export type ApplePushKeysPaginatedByAccountQueryVariables = Exact<{
accountName: Scalars['String']['input'];
after?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
}>;
export type ApplePushKeyByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, applePushKeys: Array<{ __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> }> } } };
export type ApplePushKeysPaginatedByAccountQuery = { __typename?: 'RootQuery', account: { __typename?: 'AccountQuery', byName: { __typename?: 'Account', id: string, applePushKeysPaginated: { __typename?: 'AccountApplePushKeysConnection', edges: Array<{ __typename?: 'AccountApplePushKeysEdge', cursor: string, node: { __typename?: 'ApplePushKey', id: string, keyIdentifier: string, updatedAt: any, appleTeam?: { __typename?: 'AppleTeam', id: string, appleTeamIdentifier: string, appleTeamName?: string | null } | null, iosAppCredentialsList: Array<{ __typename?: 'IosAppCredentials', id: string, app: { __typename?: 'App', id: string, fullName: string, slug: string, ownerAccount: { __typename?: 'Account', id: string, name: string, ownerUserActor?: { __typename?: 'SSOUser', id: string, username: string } | { __typename?: 'User', id: string, username: string } | null, users: Array<{ __typename?: 'UserPermission', role: Role, actor: { __typename?: 'Robot', id: string } | { __typename?: 'SSOUser', id: string } | { __typename?: 'User', id: string } }> } }, appleAppIdentifier: { __typename?: 'AppleAppIdentifier', id: string, bundleIdentifier: string } }> } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null, endCursor?: string | null } } } } };
export type AppleTeamsByAccountNameQueryVariables = Exact<{
accountName: Scalars['String']['input'];
+9 -4
View File
@@ -723,16 +723,21 @@ async function getRuntimeVersionForPlatformAsync({
if (await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir)) {
try {
Log.debug('Using expo-updates runtimeversion:resolve CLI for runtime version resolution');
const extraArgs = Log.isDebug ? ['--debug'] : [];
const resolvedRuntimeVersionJSONResult = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
...extraArgs,
]);
const runtimeVersionResult = JSON.parse(resolvedRuntimeVersionJSONResult);
if (runtimeVersionResult.fingerprintSources) {
Log.debug(`Resolved fingeprint runtime version for platform "${platform}". Sources:`);
Log.debug(runtimeVersionResult.fingerprintSources);
}
Log.debug('runtimeversion:resolve output:');
Log.debug(resolvedRuntimeVersionJSONResult);
return nullthrows(
runtimeVersionResult.runtimeVersion,
`Unable to determine runtime version for ${
@@ -24,16 +24,21 @@ export async function resolveRuntimeVersionAsync({
}
try {
Log.debug('Using expo-updates runtimeversion:resolve CLI for runtime version resolution');
const extraArgs = Log.isDebug ? ['--debug'] : [];
const resolvedRuntimeVersionJSONResult = await expoUpdatesCommandAsync(projectDir, [
'runtimeversion:resolve',
'--platform',
platform,
...extraArgs,
]);
const runtimeVersionResult = JSON.parse(resolvedRuntimeVersionJSONResult);
if (runtimeVersionResult.fingerprintSources) {
Log.debug(`Resolved fingeprint runtime version for platform "${platform}". Sources:`);
Log.debug(runtimeVersionResult.fingerprintSources);
}
Log.debug('runtimeversion:resolve output:');
Log.debug(resolvedRuntimeVersionJSONResult);
return runtimeVersionResult.runtimeVersion ?? null;
} catch (e: any) {
// if expo-updates is not installed, there's no need for a runtime version in the build
@@ -1,10 +1,15 @@
import { PageInfo } from '../../graphql/generated';
import { promptAsync } from '../../prompts';
import {
Connection,
Edge,
FilterPagination,
NEXT_PAGE_OPTION,
PAGE_SIZE,
PREV_PAGE_OPTION,
PaginatedGetterAsync,
QueryParams,
fetchEntireDatasetAsync,
selectPaginatedAsync,
} from '../relay';
@@ -780,3 +785,55 @@ describe(selectPaginatedAsync, () => {
expect(getTitleAsync).toHaveBeenCalledWith(node3);
});
});
describe(selectPaginatedAsync, () => {
const mockDataset = Array.from({ length: 50 }, (_, idx) => ({ id: idx + 1 }));
const testPaginatedGetterAsync: PaginatedGetterAsync<object> = async (
relayArgs: QueryParams
): Promise<Connection<object>> => {
const startIdx = relayArgs.after ? Number(relayArgs.after) : 0;
const endIdx = startIdx + (relayArgs.first || PAGE_SIZE);
const hasNextPage = endIdx < mockDataset.length;
const hasPreviousPage = startIdx > 0;
const edges: Edge<object>[] = mockDataset
.slice(startIdx, endIdx)
.map(node => ({ cursor: String(node.id), node }));
const pageInfo: PageInfo = {
hasNextPage,
hasPreviousPage,
endCursor: hasNextPage ? String(endIdx) : undefined,
};
return {
edges,
pageInfo,
};
};
afterEach(() => {
jest.clearAllMocks();
});
test('getting an entire paginated dataset', async () => {
const data = await fetchEntireDatasetAsync({
paginatedGetterAsync: testPaginatedGetterAsync,
});
expect(data).toEqual(mockDataset);
});
test('getting an empty paginated dataset', async () => {
const emptyPaginatedGetterAsync = async (): Promise<Connection<object>> => {
return {
edges: [],
pageInfo: {
hasNextPage: false,
hasPreviousPage: false,
},
};
};
const data = await fetchEntireDatasetAsync({
paginatedGetterAsync: emptyPaginatedGetterAsync,
});
expect(data).toEqual([]);
});
});
+11 -5
View File
@@ -5,6 +5,7 @@ import { link } from '../log';
export class ExpoUpdatesCLIModuleNotFoundError extends Error {}
export class ExpoUpdatesCLIInvalidCommandError extends Error {}
export class ExpoUpdatesCLICommandFailedError extends Error {}
export async function expoUpdatesCommandAsync(projectDir: string, args: string[]): Promise<string> {
let expoUpdatesCli;
@@ -24,13 +25,18 @@ export async function expoUpdatesCommandAsync(projectDir: string, args: string[]
}
try {
return (await spawnAsync(expoUpdatesCli, args)).stdout;
return (await spawnAsync(expoUpdatesCli, args, { stdio: 'pipe' })).stdout;
} catch (e: any) {
if (e.stderr && typeof e.stderr === 'string' && e.stderr.includes('Invalid command')) {
throw new ExpoUpdatesCLIInvalidCommandError(
`The command specified by ${args} was not valid in the \`expo-updates\` CLI.`
);
if (e.stderr && typeof e.stderr === 'string') {
if (e.stderr.includes('Invalid command')) {
throw new ExpoUpdatesCLIInvalidCommandError(
`The command specified by ${args} was not valid in the \`expo-updates\` CLI.`
);
} else {
throw new ExpoUpdatesCLICommandFailedError(e.stderr);
}
}
throw e;
}
}
+49
View File
@@ -1,4 +1,5 @@
import assert from 'assert';
import cliProgress from 'cli-progress';
import { PageInfo } from '../graphql/generated';
import { promptAsync } from '../prompts';
@@ -356,3 +357,51 @@ async function selectPaginatedInternalAsync<T>({
return selectedItem as T;
}
}
export type PaginatedGetterAsync<Node> = (relayArgs: QueryParams) => Promise<Connection<Node>>;
export const PAGE_SIZE = 20;
export async function fetchEntireDatasetAsync<Node>({
paginatedGetterAsync,
progressBarLabel,
}: {
paginatedGetterAsync: PaginatedGetterAsync<Node>;
progressBarLabel?: string;
}): Promise<Node[]> {
// No way to know the total count of items beforehand
let totalEstimatedWork = 10;
const queueProgressBar = new cliProgress.SingleBar(
{ format: `|{bar}| ${progressBarLabel}` },
cliProgress.Presets.rect
);
const data: Node[] = [];
let cursor = undefined;
let didStartProgressBar = false;
let progress = 0;
while (true) {
const connection = await paginatedGetterAsync({ first: PAGE_SIZE, after: cursor });
const nodes = connection.edges.map(edge => edge.node);
const hasNextPage = connection.pageInfo.hasNextPage;
data.push(...nodes);
if (!hasNextPage) {
break;
}
cursor = connection.pageInfo.endCursor ?? undefined;
if (!didStartProgressBar) {
// only show the progress bar if user has more than 1 page of items
queueProgressBar.start(totalEstimatedWork, 0);
didStartProgressBar = true;
}
progress++;
queueProgressBar.update(progress);
if (progress >= totalEstimatedWork) {
totalEstimatedWork = 8 * totalEstimatedWork;
queueProgressBar.setTotal(totalEstimatedWork);
}
}
if (didStartProgressBar) {
queueProgressBar.update(totalEstimatedWork);
queueProgressBar.stop();
}
return data;
}