@hot-updater/android-helper 1.1.3 → 1.2.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1375 -379
- package/dist/index.d.cts +237 -17
- package/dist/index.d.mts +238 -17
- package/dist/index.mjs +1357 -379
- package/package.json +5 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CredentialRequest, CredentialResolver, Credentials } from "@hot-updater/cli-tools";
|
|
2
|
+
import { NativeBuildAndroidScheme } from "@hot-updater/plugin-core";
|
|
2
3
|
//#region src/utils/enrichNativeBuildAndroidScheme.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Validated scheme filled nullish values with default values.
|
|
5
6
|
*/
|
|
6
|
-
type EnrichedNativeBuildAndroidScheme = Required<NativeBuildAndroidScheme> & {
|
|
7
|
+
type EnrichedNativeBuildAndroidScheme = Required<Omit<NativeBuildAndroidScheme, "signing">> & Pick<NativeBuildAndroidScheme, "signing"> & {
|
|
7
8
|
hotUpdaterSchemeName: string;
|
|
8
9
|
};
|
|
9
10
|
declare const enrichNativeBuildAndroidScheme: ({ schemeConfig, hotUpdaterSchemeName }: {
|
|
@@ -12,28 +13,247 @@ declare const enrichNativeBuildAndroidScheme: ({ schemeConfig, hotUpdaterSchemeN
|
|
|
12
13
|
}) => Promise<EnrichedNativeBuildAndroidScheme>;
|
|
13
14
|
//#endregion
|
|
14
15
|
//#region src/buildAndroid.d.ts
|
|
15
|
-
declare const buildAndroid: ({ schemeConfig }: {
|
|
16
|
+
declare const buildAndroid: ({ schemeConfig, minBundleId, credentials }: {
|
|
16
17
|
schemeConfig: EnrichedNativeBuildAndroidScheme;
|
|
18
|
+
/** The MIN_BUNDLE_ID the build compiles in. */
|
|
19
|
+
minBundleId?: string;
|
|
20
|
+
/** Resolves the scheme's `signing` keystore, when it signs with one. */
|
|
21
|
+
credentials?: Pick<CredentialResolver, "resolve">;
|
|
17
22
|
}) => Promise<{
|
|
18
23
|
buildDirectory: string;
|
|
19
24
|
buildArtifactPath: string;
|
|
25
|
+
/** What the built artifact reports, or undefined without aapt2. */
|
|
26
|
+
builtApp?: {
|
|
27
|
+
appVersion: string | null;
|
|
28
|
+
/** undefined when the artifact's channel cannot be read exactly. */
|
|
29
|
+
channel?: string | null;
|
|
30
|
+
/** The manifest's `versionCode`. */
|
|
31
|
+
buildNumber: string | null;
|
|
32
|
+
};
|
|
20
33
|
}>;
|
|
21
34
|
//#endregion
|
|
22
|
-
//#region src/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
//#region src/uploadToPlay.d.ts
|
|
36
|
+
/**
|
|
37
|
+
* Google Play refused the upload: it already has a bundle or APK with the
|
|
38
|
+
* `.aab`'s version code, from this or another upload, and takes each version
|
|
39
|
+
* code once.
|
|
40
|
+
*/
|
|
41
|
+
declare class PlayVersionCodeUsedError extends Error {
|
|
42
|
+
readonly name = "PlayVersionCodeUsedError";
|
|
43
|
+
constructor(options?: ErrorOptions);
|
|
28
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether Google Play's internal testing track already releases the
|
|
47
|
+
* `.aab`'s version code, as when a reused native build was uploaded
|
|
48
|
+
* before. It reads the track in an edit it then deletes, changing nothing.
|
|
49
|
+
*/
|
|
50
|
+
declare const findPlayInternalRelease: ({ versionCode, packageName, serviceAccount: { json }, fetch }: {
|
|
51
|
+
versionCode: number;
|
|
52
|
+
/** The application ID the `.aab` was built with. */
|
|
53
|
+
packageName: string;
|
|
54
|
+
serviceAccount: Credentials["play-service-account"];
|
|
55
|
+
fetch?: typeof globalThis.fetch;
|
|
56
|
+
}) => Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Throws when the `.aab` is signed with the Android debug keystore, which
|
|
59
|
+
* Google Play refuses: a release build type left on `signingConfigs.debug`,
|
|
60
|
+
* as React Native's template ships it. It reads the signer with the JDK's
|
|
61
|
+
* `keytool`, which Gradle needs too; without one it checks nothing.
|
|
62
|
+
*/
|
|
63
|
+
declare const assertPlaySigned: (aabPath: string) => Promise<void>;
|
|
64
|
+
interface UploadToPlayResult {
|
|
65
|
+
/** The version code Google Play read from the `.aab`. */
|
|
66
|
+
versionCode: number;
|
|
67
|
+
/** The release's status: `draft` on an app Play Console has not published. */
|
|
68
|
+
status: "completed" | "draft";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Uploads an `.aab` to Google Play's internal testing track with the Google
|
|
72
|
+
* Play Developer API: it opens an edit, uploads the bundle, releases its
|
|
73
|
+
* version code to the internal track, and commits the edit, which it
|
|
74
|
+
* deletes again when any step fails. The service account stays in memory.
|
|
75
|
+
*/
|
|
76
|
+
declare const uploadToPlay: ({ aabPath, packageName, serviceAccount: { json }, fetch, commitRetryDelayMs }: {
|
|
77
|
+
aabPath: string;
|
|
78
|
+
/** The application ID the `.aab` was built with. */
|
|
79
|
+
packageName: string;
|
|
80
|
+
serviceAccount: Credentials["play-service-account"];
|
|
81
|
+
fetch?: typeof globalThis.fetch;
|
|
82
|
+
/** The first wait before committing again an edit Google is processing. */
|
|
83
|
+
commitRetryDelayMs?: number;
|
|
84
|
+
}) => Promise<UploadToPlayResult>;
|
|
85
|
+
/**
|
|
86
|
+
* The Play service account a scheme's `.aab` uploads with: the
|
|
87
|
+
* `play-service-account` item. It reads only the config, before the native
|
|
88
|
+
* projects are written, and throws for a scheme whose build Google Play
|
|
89
|
+
* would not take as a release: an `.apk`, which Play takes only as an `.aab`
|
|
90
|
+
* from new apps, or a debug variant, which Play refuses.
|
|
91
|
+
*/
|
|
92
|
+
declare const resolvePlayUploadServiceAccount: ({ scheme, androidScheme }: {
|
|
93
|
+
/** The scheme's name. */
|
|
94
|
+
scheme: string;
|
|
95
|
+
androidScheme: NativeBuildAndroidScheme;
|
|
96
|
+
}) => CredentialRequest<"play-service-account">;
|
|
29
97
|
//#endregion
|
|
30
|
-
//#region src/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
98
|
+
//#region src/utils/extractBuiltInBundle.d.ts
|
|
99
|
+
/**
|
|
100
|
+
* Copies the JavaScript bundle React Native's Gradle build packed into an
|
|
101
|
+
* `.apk` (`assets/index.android.bundle`) or an `.aab`
|
|
102
|
+
* (`base/assets/index.android.bundle`) to `outputPath`: the built-in bundle,
|
|
103
|
+
* byte for byte, which no rebuild reproduces. It reads only the archive's
|
|
104
|
+
* directory and that entry, streamed, so a large artifact stays on disk.
|
|
105
|
+
*/
|
|
106
|
+
declare const extractBuiltInBundle: ({ artifactPath, outputPath }: {
|
|
107
|
+
artifactPath: string;
|
|
108
|
+
outputPath: string;
|
|
109
|
+
}) => Promise<void>;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/utils/readBuiltApp.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* What the built `.apk` or `.aab` reports at runtime: the `versionName` and
|
|
114
|
+
* the `com.hotupdater.CHANNEL` meta-data Gradle merged into its manifest,
|
|
115
|
+
* from flavors, build types and `versionNameSuffix`. Without aapt2 it
|
|
116
|
+
* returns undefined, and the build reports the project's values.
|
|
117
|
+
*/
|
|
118
|
+
declare const readBuiltApp: ({ artifactPath, androidProjectPath }: {
|
|
119
|
+
artifactPath: string;
|
|
120
|
+
androidProjectPath: string;
|
|
34
121
|
}) => Promise<{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
122
|
+
appVersion: string | null;
|
|
123
|
+
/** undefined when the artifact's channel cannot be read exactly. */
|
|
124
|
+
channel?: string | null;
|
|
125
|
+
/** The manifest's `versionCode`. */
|
|
126
|
+
buildNumber: string | null;
|
|
127
|
+
} | undefined>;
|
|
128
|
+
/**
|
|
129
|
+
* The application ID of the built `.apk` or `.aab`, the package name Google
|
|
130
|
+
* Play files it under, with the suffixes flavors and build types add.
|
|
131
|
+
* undefined without aapt2.
|
|
132
|
+
*/
|
|
133
|
+
declare const readBuiltPackageName: ({ artifactPath, androidProjectPath }: {
|
|
134
|
+
artifactPath: string;
|
|
135
|
+
androidProjectPath: string;
|
|
136
|
+
}) => Promise<string | undefined>;
|
|
137
|
+
/**
|
|
138
|
+
* The version code of the built `.apk` or `.aab`, which Google Play files
|
|
139
|
+
* its releases by. undefined without aapt2, or when the manifest has none.
|
|
140
|
+
*/
|
|
141
|
+
declare const readBuiltVersionCode: ({ artifactPath, androidProjectPath }: {
|
|
142
|
+
artifactPath: string;
|
|
143
|
+
androidProjectPath: string;
|
|
144
|
+
}) => Promise<number | undefined>;
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/google/types.d.ts
|
|
147
|
+
/** What stopped Hot Updater from issuing the Play service account key. */
|
|
148
|
+
type PlayServiceAccountErrorCode =
|
|
149
|
+
/** No OAuth client to sign in with, or Google refused it. */
|
|
150
|
+
"sign-in-not-configured" |
|
|
151
|
+
/** The browser sign-in was cancelled, refused, or timed out. */
|
|
152
|
+
"sign-in-cancelled" |
|
|
153
|
+
/** The account unticked a scope the setup needs on Google's consent screen. */
|
|
154
|
+
"scope-not-granted" |
|
|
155
|
+
/** The developer account ID names no Play Console account. */
|
|
156
|
+
"developer-not-found" |
|
|
157
|
+
/** The Google Account is no admin of the Play Console developer account. */
|
|
158
|
+
"not-play-admin" |
|
|
159
|
+
/** Google Play has no app with the package name in the developer account. */
|
|
160
|
+
"app-not-found" |
|
|
161
|
+
/** The Google Account may not create a Google Cloud project. */
|
|
162
|
+
"project-create-denied" |
|
|
163
|
+
/** The Google Account has no Google Cloud project quota left. */
|
|
164
|
+
"project-quota" |
|
|
165
|
+
/** The Google Account may not enable APIs or create service accounts in the project. */
|
|
166
|
+
"project-access-denied" |
|
|
167
|
+
/** Google is still enabling an API, or it is disabled in the OAuth client's project. */
|
|
168
|
+
"api-not-enabled" |
|
|
169
|
+
/** An organization policy (`iam.disableServiceAccountKeyCreation`) forbids keys. */
|
|
170
|
+
"key-creation-disabled";
|
|
171
|
+
/** A named failure of `issuePlayServiceAccount`, with what to do in its message. */
|
|
172
|
+
declare class PlayServiceAccountError extends Error {
|
|
173
|
+
readonly code: PlayServiceAccountErrorCode;
|
|
174
|
+
constructor(code: PlayServiceAccountErrorCode, message: string, options?: {
|
|
175
|
+
cause?: unknown;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A Google OAuth client of type "Desktop app". Google treats an installed
|
|
180
|
+
* app's client secret as public, so it ships with the client ID.
|
|
181
|
+
*/
|
|
182
|
+
interface GoogleOAuthClient {
|
|
183
|
+
readonly clientId: string;
|
|
184
|
+
readonly clientSecret?: string;
|
|
185
|
+
}
|
|
186
|
+
/** The environment variables that replace Hot Updater's Google OAuth client. */
|
|
187
|
+
declare const GOOGLE_OAUTH_CLIENT_ENV_NAMES: {
|
|
188
|
+
readonly clientId: "HOT_UPDATER_GOOGLE_OAUTH_CLIENT_ID";
|
|
189
|
+
readonly clientSecret: "HOT_UPDATER_GOOGLE_OAUTH_CLIENT_SECRET";
|
|
190
|
+
};
|
|
191
|
+
/** The service account Hot Updater creates, `hot-updater-play@<project>.iam.gserviceaccount.com`. */
|
|
192
|
+
declare const PLAY_SERVICE_ACCOUNT_ID = "hot-updater-play";
|
|
193
|
+
/** Where a Play Console admin finds the developer account ID. */
|
|
194
|
+
declare const PLAY_CONSOLE_URL = "https://play.google.com/console";
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/playServiceAccount.d.ts
|
|
197
|
+
/**
|
|
198
|
+
* Hot Updater's Google OAuth client, a "Desktop app" client the sign-in
|
|
199
|
+
* opens Google's consent screen for. Empty in a build that has none, where
|
|
200
|
+
* `HOT_UPDATER_GOOGLE_OAUTH_CLIENT_ID` and `_SECRET` name one.
|
|
201
|
+
*/
|
|
202
|
+
declare const HOT_UPDATER_GOOGLE_OAUTH_CLIENT: GoogleOAuthClient;
|
|
203
|
+
/** A Google Cloud project the signed-in account can use. */
|
|
204
|
+
interface GoogleCloudProject {
|
|
205
|
+
readonly projectId: string;
|
|
206
|
+
readonly displayName?: string;
|
|
207
|
+
}
|
|
208
|
+
interface IssuePlayServiceAccountRequest {
|
|
209
|
+
/** The app's package name in Google Play, which the service account may release. */
|
|
210
|
+
readonly packageName: string;
|
|
211
|
+
/** The OAuth client to sign in with; Hot Updater's unless set. */
|
|
212
|
+
readonly oauthClient?: GoogleOAuthClient;
|
|
213
|
+
/** Sees the sign-in URL, to print it and open it in a browser. */
|
|
214
|
+
readonly onSignInUrl: (url: string) => Promise<void> | void;
|
|
215
|
+
/** Asks for the Play Console developer account ID, after the sign-in. */
|
|
216
|
+
readonly askDeveloperId: () => Promise<string>;
|
|
217
|
+
/**
|
|
218
|
+
* Sees the account's projects when there are any, and returns the one to
|
|
219
|
+
* create the service account in, or undefined to create a project.
|
|
220
|
+
*/
|
|
221
|
+
readonly chooseProject: (projects: readonly GoogleCloudProject[]) => Promise<string | undefined>;
|
|
222
|
+
/** Reports each step, such as "Creating the service account". */
|
|
223
|
+
readonly onStep?: (message: string) => void;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* A Play service account's JSON key, just created, with the access token
|
|
227
|
+
* of the sign-in it was created in. `revoke` deletes the key while the
|
|
228
|
+
* sign-in lasts, and `dispose` ends the sign-in.
|
|
229
|
+
*/
|
|
230
|
+
interface IssuedPlayServiceAccount {
|
|
231
|
+
/** The JSON key file, as Google Cloud downloads it. */
|
|
232
|
+
readonly json: string;
|
|
233
|
+
/** The service account's email, the Play Console user it releases as. */
|
|
234
|
+
readonly email: string;
|
|
235
|
+
readonly projectId: string;
|
|
236
|
+
readonly developerId: string;
|
|
237
|
+
/** The key's ID, as Google Cloud lists it under the service account's keys. */
|
|
238
|
+
readonly keyId: string;
|
|
239
|
+
/** Deletes the key with the same sign-in; whether Google Cloud did. */
|
|
240
|
+
revoke(): Promise<boolean>;
|
|
241
|
+
/** Ends the sign-in: Google revokes its access token. */
|
|
242
|
+
dispose(): Promise<void>;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Signs in with Google and issues a service account key that releases the
|
|
246
|
+
* app to Google Play: the developer signs in on Google's own consent
|
|
247
|
+
* screen, in a browser, and the caller never sees the password. Nothing of
|
|
248
|
+
* the sign-in outlives `dispose`.
|
|
249
|
+
*/
|
|
250
|
+
type IssuePlayServiceAccount = (request: IssuePlayServiceAccountRequest) => Promise<IssuedPlayServiceAccount>;
|
|
251
|
+
/**
|
|
252
|
+
* Hot Updater's issuer, the one place that picks how it is done: Google's
|
|
253
|
+
* OAuth for installed apps, then the Cloud Resource Manager, Service Usage,
|
|
254
|
+
* IAM, and Play Developer APIs. Another implementation of
|
|
255
|
+
* `IssuePlayServiceAccount` replaces it here without touching its callers.
|
|
256
|
+
*/
|
|
257
|
+
declare const issuePlayServiceAccount: IssuePlayServiceAccount;
|
|
38
258
|
//#endregion
|
|
39
|
-
export { type
|
|
259
|
+
export { type EnrichedNativeBuildAndroidScheme, GOOGLE_OAUTH_CLIENT_ENV_NAMES, type GoogleCloudProject, type GoogleOAuthClient, HOT_UPDATER_GOOGLE_OAUTH_CLIENT, type IssuePlayServiceAccount, type IssuePlayServiceAccountRequest, type IssuedPlayServiceAccount, PLAY_CONSOLE_URL, PLAY_SERVICE_ACCOUNT_ID, PlayServiceAccountError, type PlayServiceAccountErrorCode, PlayVersionCodeUsedError, type UploadToPlayResult, assertPlaySigned, buildAndroid, enrichNativeBuildAndroidScheme, extractBuiltInBundle, findPlayInternalRelease, issuePlayServiceAccount, readBuiltApp, readBuiltPackageName, readBuiltVersionCode, resolvePlayUploadServiceAccount, uploadToPlay };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CredentialRequest, CredentialResolver, Credentials } from "@hot-updater/cli-tools";
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
import { NativeBuildAndroidScheme } from "@hot-updater/plugin-core";
|
|
2
4
|
//#region src/utils/enrichNativeBuildAndroidScheme.d.ts
|
|
3
5
|
/**
|
|
4
6
|
* Validated scheme filled nullish values with default values.
|
|
5
7
|
*/
|
|
6
|
-
type EnrichedNativeBuildAndroidScheme = Required<NativeBuildAndroidScheme> & {
|
|
8
|
+
type EnrichedNativeBuildAndroidScheme = Required<Omit<NativeBuildAndroidScheme, "signing">> & Pick<NativeBuildAndroidScheme, "signing"> & {
|
|
7
9
|
hotUpdaterSchemeName: string;
|
|
8
10
|
};
|
|
9
11
|
declare const enrichNativeBuildAndroidScheme: ({ schemeConfig, hotUpdaterSchemeName }: {
|
|
@@ -12,28 +14,247 @@ declare const enrichNativeBuildAndroidScheme: ({ schemeConfig, hotUpdaterSchemeN
|
|
|
12
14
|
}) => Promise<EnrichedNativeBuildAndroidScheme>;
|
|
13
15
|
//#endregion
|
|
14
16
|
//#region src/buildAndroid.d.ts
|
|
15
|
-
declare const buildAndroid: ({ schemeConfig }: {
|
|
17
|
+
declare const buildAndroid: ({ schemeConfig, minBundleId, credentials }: {
|
|
16
18
|
schemeConfig: EnrichedNativeBuildAndroidScheme;
|
|
19
|
+
/** The MIN_BUNDLE_ID the build compiles in. */
|
|
20
|
+
minBundleId?: string;
|
|
21
|
+
/** Resolves the scheme's `signing` keystore, when it signs with one. */
|
|
22
|
+
credentials?: Pick<CredentialResolver, "resolve">;
|
|
17
23
|
}) => Promise<{
|
|
18
24
|
buildDirectory: string;
|
|
19
25
|
buildArtifactPath: string;
|
|
26
|
+
/** What the built artifact reports, or undefined without aapt2. */
|
|
27
|
+
builtApp?: {
|
|
28
|
+
appVersion: string | null;
|
|
29
|
+
/** undefined when the artifact's channel cannot be read exactly. */
|
|
30
|
+
channel?: string | null;
|
|
31
|
+
/** The manifest's `versionCode`. */
|
|
32
|
+
buildNumber: string | null;
|
|
33
|
+
};
|
|
20
34
|
}>;
|
|
21
35
|
//#endregion
|
|
22
|
-
//#region src/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
//#region src/uploadToPlay.d.ts
|
|
37
|
+
/**
|
|
38
|
+
* Google Play refused the upload: it already has a bundle or APK with the
|
|
39
|
+
* `.aab`'s version code, from this or another upload, and takes each version
|
|
40
|
+
* code once.
|
|
41
|
+
*/
|
|
42
|
+
declare class PlayVersionCodeUsedError extends Error {
|
|
43
|
+
readonly name = "PlayVersionCodeUsedError";
|
|
44
|
+
constructor(options?: ErrorOptions);
|
|
28
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Whether Google Play's internal testing track already releases the
|
|
48
|
+
* `.aab`'s version code, as when a reused native build was uploaded
|
|
49
|
+
* before. It reads the track in an edit it then deletes, changing nothing.
|
|
50
|
+
*/
|
|
51
|
+
declare const findPlayInternalRelease: ({ versionCode, packageName, serviceAccount: { json }, fetch }: {
|
|
52
|
+
versionCode: number;
|
|
53
|
+
/** The application ID the `.aab` was built with. */
|
|
54
|
+
packageName: string;
|
|
55
|
+
serviceAccount: Credentials["play-service-account"];
|
|
56
|
+
fetch?: typeof globalThis.fetch;
|
|
57
|
+
}) => Promise<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Throws when the `.aab` is signed with the Android debug keystore, which
|
|
60
|
+
* Google Play refuses: a release build type left on `signingConfigs.debug`,
|
|
61
|
+
* as React Native's template ships it. It reads the signer with the JDK's
|
|
62
|
+
* `keytool`, which Gradle needs too; without one it checks nothing.
|
|
63
|
+
*/
|
|
64
|
+
declare const assertPlaySigned: (aabPath: string) => Promise<void>;
|
|
65
|
+
interface UploadToPlayResult {
|
|
66
|
+
/** The version code Google Play read from the `.aab`. */
|
|
67
|
+
versionCode: number;
|
|
68
|
+
/** The release's status: `draft` on an app Play Console has not published. */
|
|
69
|
+
status: "completed" | "draft";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Uploads an `.aab` to Google Play's internal testing track with the Google
|
|
73
|
+
* Play Developer API: it opens an edit, uploads the bundle, releases its
|
|
74
|
+
* version code to the internal track, and commits the edit, which it
|
|
75
|
+
* deletes again when any step fails. The service account stays in memory.
|
|
76
|
+
*/
|
|
77
|
+
declare const uploadToPlay: ({ aabPath, packageName, serviceAccount: { json }, fetch, commitRetryDelayMs }: {
|
|
78
|
+
aabPath: string;
|
|
79
|
+
/** The application ID the `.aab` was built with. */
|
|
80
|
+
packageName: string;
|
|
81
|
+
serviceAccount: Credentials["play-service-account"];
|
|
82
|
+
fetch?: typeof globalThis.fetch;
|
|
83
|
+
/** The first wait before committing again an edit Google is processing. */
|
|
84
|
+
commitRetryDelayMs?: number;
|
|
85
|
+
}) => Promise<UploadToPlayResult>;
|
|
86
|
+
/**
|
|
87
|
+
* The Play service account a scheme's `.aab` uploads with: the
|
|
88
|
+
* `play-service-account` item. It reads only the config, before the native
|
|
89
|
+
* projects are written, and throws for a scheme whose build Google Play
|
|
90
|
+
* would not take as a release: an `.apk`, which Play takes only as an `.aab`
|
|
91
|
+
* from new apps, or a debug variant, which Play refuses.
|
|
92
|
+
*/
|
|
93
|
+
declare const resolvePlayUploadServiceAccount: ({ scheme, androidScheme }: {
|
|
94
|
+
/** The scheme's name. */
|
|
95
|
+
scheme: string;
|
|
96
|
+
androidScheme: NativeBuildAndroidScheme;
|
|
97
|
+
}) => CredentialRequest<"play-service-account">;
|
|
29
98
|
//#endregion
|
|
30
|
-
//#region src/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
99
|
+
//#region src/utils/extractBuiltInBundle.d.ts
|
|
100
|
+
/**
|
|
101
|
+
* Copies the JavaScript bundle React Native's Gradle build packed into an
|
|
102
|
+
* `.apk` (`assets/index.android.bundle`) or an `.aab`
|
|
103
|
+
* (`base/assets/index.android.bundle`) to `outputPath`: the built-in bundle,
|
|
104
|
+
* byte for byte, which no rebuild reproduces. It reads only the archive's
|
|
105
|
+
* directory and that entry, streamed, so a large artifact stays on disk.
|
|
106
|
+
*/
|
|
107
|
+
declare const extractBuiltInBundle: ({ artifactPath, outputPath }: {
|
|
108
|
+
artifactPath: string;
|
|
109
|
+
outputPath: string;
|
|
110
|
+
}) => Promise<void>;
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/utils/readBuiltApp.d.ts
|
|
113
|
+
/**
|
|
114
|
+
* What the built `.apk` or `.aab` reports at runtime: the `versionName` and
|
|
115
|
+
* the `com.hotupdater.CHANNEL` meta-data Gradle merged into its manifest,
|
|
116
|
+
* from flavors, build types and `versionNameSuffix`. Without aapt2 it
|
|
117
|
+
* returns undefined, and the build reports the project's values.
|
|
118
|
+
*/
|
|
119
|
+
declare const readBuiltApp: ({ artifactPath, androidProjectPath }: {
|
|
120
|
+
artifactPath: string;
|
|
121
|
+
androidProjectPath: string;
|
|
34
122
|
}) => Promise<{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
123
|
+
appVersion: string | null;
|
|
124
|
+
/** undefined when the artifact's channel cannot be read exactly. */
|
|
125
|
+
channel?: string | null;
|
|
126
|
+
/** The manifest's `versionCode`. */
|
|
127
|
+
buildNumber: string | null;
|
|
128
|
+
} | undefined>;
|
|
129
|
+
/**
|
|
130
|
+
* The application ID of the built `.apk` or `.aab`, the package name Google
|
|
131
|
+
* Play files it under, with the suffixes flavors and build types add.
|
|
132
|
+
* undefined without aapt2.
|
|
133
|
+
*/
|
|
134
|
+
declare const readBuiltPackageName: ({ artifactPath, androidProjectPath }: {
|
|
135
|
+
artifactPath: string;
|
|
136
|
+
androidProjectPath: string;
|
|
137
|
+
}) => Promise<string | undefined>;
|
|
138
|
+
/**
|
|
139
|
+
* The version code of the built `.apk` or `.aab`, which Google Play files
|
|
140
|
+
* its releases by. undefined without aapt2, or when the manifest has none.
|
|
141
|
+
*/
|
|
142
|
+
declare const readBuiltVersionCode: ({ artifactPath, androidProjectPath }: {
|
|
143
|
+
artifactPath: string;
|
|
144
|
+
androidProjectPath: string;
|
|
145
|
+
}) => Promise<number | undefined>;
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/google/types.d.ts
|
|
148
|
+
/** What stopped Hot Updater from issuing the Play service account key. */
|
|
149
|
+
type PlayServiceAccountErrorCode =
|
|
150
|
+
/** No OAuth client to sign in with, or Google refused it. */
|
|
151
|
+
"sign-in-not-configured" |
|
|
152
|
+
/** The browser sign-in was cancelled, refused, or timed out. */
|
|
153
|
+
"sign-in-cancelled" |
|
|
154
|
+
/** The account unticked a scope the setup needs on Google's consent screen. */
|
|
155
|
+
"scope-not-granted" |
|
|
156
|
+
/** The developer account ID names no Play Console account. */
|
|
157
|
+
"developer-not-found" |
|
|
158
|
+
/** The Google Account is no admin of the Play Console developer account. */
|
|
159
|
+
"not-play-admin" |
|
|
160
|
+
/** Google Play has no app with the package name in the developer account. */
|
|
161
|
+
"app-not-found" |
|
|
162
|
+
/** The Google Account may not create a Google Cloud project. */
|
|
163
|
+
"project-create-denied" |
|
|
164
|
+
/** The Google Account has no Google Cloud project quota left. */
|
|
165
|
+
"project-quota" |
|
|
166
|
+
/** The Google Account may not enable APIs or create service accounts in the project. */
|
|
167
|
+
"project-access-denied" |
|
|
168
|
+
/** Google is still enabling an API, or it is disabled in the OAuth client's project. */
|
|
169
|
+
"api-not-enabled" |
|
|
170
|
+
/** An organization policy (`iam.disableServiceAccountKeyCreation`) forbids keys. */
|
|
171
|
+
"key-creation-disabled";
|
|
172
|
+
/** A named failure of `issuePlayServiceAccount`, with what to do in its message. */
|
|
173
|
+
declare class PlayServiceAccountError extends Error {
|
|
174
|
+
readonly code: PlayServiceAccountErrorCode;
|
|
175
|
+
constructor(code: PlayServiceAccountErrorCode, message: string, options?: {
|
|
176
|
+
cause?: unknown;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A Google OAuth client of type "Desktop app". Google treats an installed
|
|
181
|
+
* app's client secret as public, so it ships with the client ID.
|
|
182
|
+
*/
|
|
183
|
+
interface GoogleOAuthClient {
|
|
184
|
+
readonly clientId: string;
|
|
185
|
+
readonly clientSecret?: string;
|
|
186
|
+
}
|
|
187
|
+
/** The environment variables that replace Hot Updater's Google OAuth client. */
|
|
188
|
+
declare const GOOGLE_OAUTH_CLIENT_ENV_NAMES: {
|
|
189
|
+
readonly clientId: "HOT_UPDATER_GOOGLE_OAUTH_CLIENT_ID";
|
|
190
|
+
readonly clientSecret: "HOT_UPDATER_GOOGLE_OAUTH_CLIENT_SECRET";
|
|
191
|
+
};
|
|
192
|
+
/** The service account Hot Updater creates, `hot-updater-play@<project>.iam.gserviceaccount.com`. */
|
|
193
|
+
declare const PLAY_SERVICE_ACCOUNT_ID = "hot-updater-play";
|
|
194
|
+
/** Where a Play Console admin finds the developer account ID. */
|
|
195
|
+
declare const PLAY_CONSOLE_URL = "https://play.google.com/console";
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/playServiceAccount.d.ts
|
|
198
|
+
/**
|
|
199
|
+
* Hot Updater's Google OAuth client, a "Desktop app" client the sign-in
|
|
200
|
+
* opens Google's consent screen for. Empty in a build that has none, where
|
|
201
|
+
* `HOT_UPDATER_GOOGLE_OAUTH_CLIENT_ID` and `_SECRET` name one.
|
|
202
|
+
*/
|
|
203
|
+
declare const HOT_UPDATER_GOOGLE_OAUTH_CLIENT: GoogleOAuthClient;
|
|
204
|
+
/** A Google Cloud project the signed-in account can use. */
|
|
205
|
+
interface GoogleCloudProject {
|
|
206
|
+
readonly projectId: string;
|
|
207
|
+
readonly displayName?: string;
|
|
208
|
+
}
|
|
209
|
+
interface IssuePlayServiceAccountRequest {
|
|
210
|
+
/** The app's package name in Google Play, which the service account may release. */
|
|
211
|
+
readonly packageName: string;
|
|
212
|
+
/** The OAuth client to sign in with; Hot Updater's unless set. */
|
|
213
|
+
readonly oauthClient?: GoogleOAuthClient;
|
|
214
|
+
/** Sees the sign-in URL, to print it and open it in a browser. */
|
|
215
|
+
readonly onSignInUrl: (url: string) => Promise<void> | void;
|
|
216
|
+
/** Asks for the Play Console developer account ID, after the sign-in. */
|
|
217
|
+
readonly askDeveloperId: () => Promise<string>;
|
|
218
|
+
/**
|
|
219
|
+
* Sees the account's projects when there are any, and returns the one to
|
|
220
|
+
* create the service account in, or undefined to create a project.
|
|
221
|
+
*/
|
|
222
|
+
readonly chooseProject: (projects: readonly GoogleCloudProject[]) => Promise<string | undefined>;
|
|
223
|
+
/** Reports each step, such as "Creating the service account". */
|
|
224
|
+
readonly onStep?: (message: string) => void;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* A Play service account's JSON key, just created, with the access token
|
|
228
|
+
* of the sign-in it was created in. `revoke` deletes the key while the
|
|
229
|
+
* sign-in lasts, and `dispose` ends the sign-in.
|
|
230
|
+
*/
|
|
231
|
+
interface IssuedPlayServiceAccount {
|
|
232
|
+
/** The JSON key file, as Google Cloud downloads it. */
|
|
233
|
+
readonly json: string;
|
|
234
|
+
/** The service account's email, the Play Console user it releases as. */
|
|
235
|
+
readonly email: string;
|
|
236
|
+
readonly projectId: string;
|
|
237
|
+
readonly developerId: string;
|
|
238
|
+
/** The key's ID, as Google Cloud lists it under the service account's keys. */
|
|
239
|
+
readonly keyId: string;
|
|
240
|
+
/** Deletes the key with the same sign-in; whether Google Cloud did. */
|
|
241
|
+
revoke(): Promise<boolean>;
|
|
242
|
+
/** Ends the sign-in: Google revokes its access token. */
|
|
243
|
+
dispose(): Promise<void>;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Signs in with Google and issues a service account key that releases the
|
|
247
|
+
* app to Google Play: the developer signs in on Google's own consent
|
|
248
|
+
* screen, in a browser, and the caller never sees the password. Nothing of
|
|
249
|
+
* the sign-in outlives `dispose`.
|
|
250
|
+
*/
|
|
251
|
+
type IssuePlayServiceAccount = (request: IssuePlayServiceAccountRequest) => Promise<IssuedPlayServiceAccount>;
|
|
252
|
+
/**
|
|
253
|
+
* Hot Updater's issuer, the one place that picks how it is done: Google's
|
|
254
|
+
* OAuth for installed apps, then the Cloud Resource Manager, Service Usage,
|
|
255
|
+
* IAM, and Play Developer APIs. Another implementation of
|
|
256
|
+
* `IssuePlayServiceAccount` replaces it here without touching its callers.
|
|
257
|
+
*/
|
|
258
|
+
declare const issuePlayServiceAccount: IssuePlayServiceAccount;
|
|
38
259
|
//#endregion
|
|
39
|
-
export { type
|
|
260
|
+
export { type EnrichedNativeBuildAndroidScheme, GOOGLE_OAUTH_CLIENT_ENV_NAMES, type GoogleCloudProject, type GoogleOAuthClient, HOT_UPDATER_GOOGLE_OAUTH_CLIENT, type IssuePlayServiceAccount, type IssuePlayServiceAccountRequest, type IssuedPlayServiceAccount, PLAY_CONSOLE_URL, PLAY_SERVICE_ACCOUNT_ID, PlayServiceAccountError, type PlayServiceAccountErrorCode, PlayVersionCodeUsedError, type UploadToPlayResult, assertPlaySigned, buildAndroid, enrichNativeBuildAndroidScheme, extractBuiltInBundle, findPlayInternalRelease, issuePlayServiceAccount, readBuiltApp, readBuiltPackageName, readBuiltVersionCode, resolvePlayUploadServiceAccount, uploadToPlay };
|