Repository navigation
feat(cli): expo APNs key setup on @expo/apple-utils - #1994
ArnabChatterjee20k merged 3 commits into
Conversation
The expo adapter creates APNs keys with @expo/apple-utils 2.2.1 (MIT), the library eas-cli uses. A small Node script, its package.json and a lockfile pinning the package hash are embedded with go:embed and installed into the session folder with npm ci --ignore-scripts when they change. It needs Node.js 18 or later and reports apns.ErrUnavailable otherwise, before contacting Apple. apple-utils prompts on the terminal for the two-factor code and for anything the request leaves out; the request's Apple ID and password are passed as EXPO_APPLE_ID and EXPO_APPLE_PASSWORD, and EXPO_NO_KEYCHAIN=1 keeps the password out of the macOS Keychain. Its InvalidUserCredentialsError maps to apns.ErrInvalidCredentials and a full team to apns.MaxKeysError. apple-utils always creates keys for both environments, which also serve a single-environment request.
Registers the expo adapter, picked with --provider expo or APPWRITE_APNS_SETUP=expo.
🟢 Tier S · Ready to merge
Adds an Expo-backed APNs key setup adapter using an embedded Node helper and pinned Latest changes: The newest commit clarifies the no-team test scenario and asserts that the helper invocation omits
📂 Walkthrough · 7
Reviewed the commits since |
The CLI leaves the team out when none is known and lets the sign-in pick it. The test now checks that the helper then gets no --team-id.
f900aaa
into
messaging-provider-cli-apns-adapters
Stacked on #1992 (the APNs key setup adapters). This is the expo adapter, the fallback to switch to with
--provider expoorAPPWRITE_APNS_SETUP=expowhen the default setup breaks. It replaces #1989, which had the same helper before the adapter split.What
internal/apns/expo: anapns.Adapternamedexpothat creates the key with@expo/apple-utils2.2.1 (MIT), the library eas-cli uses (seepushKey.ts).appwrite init apns --create-key --provider expo # or APPWRITE_APNS_SETUP=expo appwrite init apns --create-keyHow
helper/helper.js,package.jsonandpackage-lock.jsonare embedded withgo:embed. The lockfile pins the package's integrity hash.~/.appwrite/apns/expo/) and runsnpm ci --ignore-scripts. It reinstalls only when the embedded files change. A missing or old Node.js, or a failednpm ci, returnsapns.ErrUnavailablebefore anything is sent to Apple.Auth.loginAsync({ teamId }), usingauthState.contextas the request context the way eas-cli'sgetRequestContextdoes, thenKeys.createKeyAsync(ctx, { name, isApns: true })andKeys.downloadKeyAsync. With no team, apple-utils picks the account's only team or asks.EXPO_APPLE_ID/EXPO_APPLE_PASSWORD, filled by the CLI fromAPPWRITE_APPLE_ID/APPWRITE_APPLE_PASSWORD.EXPO_NO_KEYCHAIN=1keeps the password out of the macOS Keychain.InvalidUserCredentialsErrorbecomesapns.ErrInvalidCredentials.MaxKeysCreatedError, or Apple's "maximum allowed number of Keys" text, becomesapns.MaxKeysErrorwith the team's keys.environment: "all"). For--environment production|sandboxthe adapter logs that the key also covers that environment. The providers still follow--environment.Tests
nodeandnpm:--name,--outand--team-idEXPO_NO_KEYCHAIN=1and the Apple IDnpm ciof the embedded lockfile, and the helper reaching apple-utils' Apple sign-in, which then fails cleanly without a terminal. A key was created with a real Apple account through this helper.Note
This PR and the appwrite one (#1993) each add one line to
apnsAdapters(). Whichever merges second needs both:apns.NewRegistry(appwrite.New(), expo.New()).