@hot-updater/cli-tools 1.2.0-rc.7 → 1.2.0-rc.9

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.
Files changed (3) hide show
  1. package/dist/index.d.mts +281 -94
  2. package/dist/index.mjs +1153 -962
  3. package/package.json +5 -5
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Readable } from "stream";
2
2
  import { Key as Key$1 } from "node:readline";
3
- import { AnyHotUpdaterPlugin, BundleSigningAdapter, ConfigInput, ConfiguredDatabase, EngineDatabase, HotUpdaterCoreApi, LocalSigningConfig, Migrator, NativeFingerprint, NativeFingerprintOptions, Platform, PluginClientPlugin, RequiredDeep, SchemaGenerator, SecretsAdapter, SigningConfig, StorageAdapter, StorageAdapterWith, StoragePutResult, ToolingDatabase } from "@hot-updater/plugin-core";
3
+ import { AnyHotUpdaterPlugin, ConfigInput, ConfiguredDatabase, EngineDatabase, HotUpdaterCoreApi, Migrator, NativeFingerprint, NativeFingerprintOptions, Platform, PluginClientPlugin, RequiredDeep, SchemaGenerator, SecretRef, SecretsAdapter, SigningConfig, StorageAdapter, StorageAdapterWith, StoragePutResult, ToolingDatabase } from "@hot-updater/plugin-core";
4
4
  import { Readable as Readable$1, Writable } from "node:stream";
5
5
  import { ManifestArchive } from "@hot-updater/protocol";
6
6
  //#region src/BuildLogger.d.ts
@@ -19,12 +19,21 @@ interface BuildFailureSummaryConfig {
19
19
  includeEnd: boolean;
20
20
  }[];
21
21
  }
22
+ /**
23
+ * Reads the short phase a live build line shows, such as `Compiling
24
+ * React-Core · 412 files`, from each line of the tool's raw output, or
25
+ * undefined for a line that starts no phase. One reader reads one run.
26
+ */
27
+ type BuildPhaseReader = (line: string) => string | undefined;
22
28
  interface BuildLoggerConfig {
23
29
  logPrefix: string;
24
- /** Lines that should be surfaced in prompt output as important events. */
25
- importantLogPatterns: LinePattern[];
26
- /** Progress stages: stage index advances when corresponding output patterns are observed. */
27
- progressStages: LinePattern[][];
30
+ /**
31
+ * The log file to append to, such as an archive's for its export, instead
32
+ * of a new one.
33
+ */
34
+ logFilePath?: string;
35
+ /** A phase reader for each run. */
36
+ createPhaseReader: () => BuildPhaseReader;
28
37
  /** What a failure prints from the tool's raw output. */
29
38
  failureSummary: BuildFailureSummaryConfig;
30
39
  }
@@ -38,33 +47,48 @@ declare class BuildFailedError extends Error {
38
47
  readonly logPath: string | null;
39
48
  /** The lines of the tool's output the summary printed. */
40
49
  readonly summary: string[];
41
- constructor(message: string, { logPath, summary, cause }: {
50
+ /**
51
+ * What to do about it, such as accepting an agreement, which the summary
52
+ * doesn't say: the one line a command prints after it, or null.
53
+ */
54
+ readonly hint: string | null;
55
+ constructor(message: string, { logPath, summary, hint, cause }: {
42
56
  logPath: string | null;
43
57
  summary: string[];
58
+ hint?: string | null;
44
59
  cause?: unknown;
45
60
  });
46
61
  }
62
+ /**
63
+ * Runs a native build tool's output through a step: the step's live line
64
+ * shows the phase its reader finds, the log file keeps the raw output, and a
65
+ * failure prints the summary of it on stderr.
66
+ */
47
67
  declare class BuildLogger {
48
68
  private readonly config;
49
- private state;
50
69
  private logWriter?;
70
+ private step?;
51
71
  private summaryLines;
52
72
  private tailLines;
53
73
  private openBlock?;
54
- private readonly promptProgress;
55
- private readonly stageCount;
56
74
  constructor(config: BuildLoggerConfig);
57
- start(): Promise<void>;
58
75
  /**
59
- * Writes the tool's raw output to the log file and reads its failure
60
- * summary from it, and shows progress from `display`, a formatter's
61
- * output of it such as xcbeautify's, or from the raw output without one.
76
+ * Opens the log, writes `header` to it, such as the tool's command line,
77
+ * which the terminal doesn't show, and starts the step titled `title`.
62
78
  */
63
- processStream(input: Readable, { display }?: {
64
- display?: Readable;
79
+ start({ title, header }: {
80
+ title: string;
81
+ header?: string[];
65
82
  }): Promise<void>;
83
+ /**
84
+ * Writes the tool's raw output to the log file, reads its failure summary
85
+ * from it, and shows its phases on the step's line.
86
+ */
87
+ processStream(input: Readable): Promise<void>;
66
88
  /** The build log, relative to the project, or null without one. */
67
89
  get logPath(): string | null;
90
+ /** The build log's absolute path, or null without one. */
91
+ get logFilePath(): string | null;
68
92
  /**
69
93
  * The lines of the raw output a failure prints: the ones the config's
70
94
  * `failureSummary` keeps, deduplicated, or the last lines without any.
@@ -74,19 +98,18 @@ declare class BuildLogger {
74
98
  private processSummaryLine;
75
99
  private keepSummaryLine;
76
100
  private consumeProgressStream;
77
- private processProgressLine;
101
+ /**
102
+ * Ends the step with `message` and its duration, or, for a failure, as
103
+ * failed, then prints the failure summary and the log's path.
104
+ */
78
105
  stop(message?: string, success?: boolean): void;
79
106
  writeError(error: unknown): void;
80
107
  close(): Promise<void>;
81
- private updateProgress;
82
- private finishRemainingProgress;
83
- private shouldLogLine;
84
108
  /**
85
109
  * Prints the failure summary and the log's path to stderr, so a `--json`
86
110
  * command's stdout stays its JSON.
87
111
  */
88
112
  private showFailureSummary;
89
- private showLogFileLocation;
90
113
  }
91
114
  //#endregion
92
115
  //#region src/appSetup.d.ts
@@ -196,21 +219,77 @@ declare const banner: (version?: string) => string;
196
219
  declare const printBanner: (version?: string) => void;
197
220
  //#endregion
198
221
  //#region src/bundleSigning.d.ts
222
+ /** The secret `signing: secret("bundle-signing-key")` names, which `secrets issue` creates. */
223
+ declare const BUNDLE_SIGNING_KEY_SECRET = "bundle-signing-key";
224
+ /** The command that creates and stores a bundle signing key. */
225
+ declare const ISSUE_SIGNING_KEY_COMMAND = "npx hot-updater secrets issue bundle-signing-key";
226
+ /** The command that stores a bundle signing key you have. */
227
+ declare const PUT_SIGNING_KEY_COMMAND = "npx hot-updater secrets put bundle-signing-key <key.pem>";
228
+ /** What deploy and doctor say when the config sets no `signing`. */
229
+ declare const UNSIGNED_BUNDLES_WARNING = "Bundles are unsigned.";
230
+ /** The next step after `UNSIGNED_BUNDLES_WARNING`. */
231
+ declare const UNSIGNED_BUNDLES_NEXT_STEP = "To sign them, run:";
232
+ /** What deploy and doctor say when `signing` is no shape it takes. */
233
+ declare const INVALID_SIGNING_MESSAGE = "signing takes secret(\"bundle-signing-key\").";
234
+ /** The next step after `INVALID_SIGNING_MESSAGE`. */
235
+ declare const INVALID_SIGNING_NEXT_STEP = "Store your key:";
236
+ /**
237
+ * The config's `signing`, read without reading any key:
238
+ * - `on`: signs, with the private key from a secret or a file. The
239
+ * shorthand `secret("<name>")` is `{ enabled: true, privateKey }`;
240
+ * - `off`: `{ enabled: false }`, which turns signing off on purpose;
241
+ * - `unsigned`: no `signing`, which deploy and doctor warn about;
242
+ * - `invalid`: any other value, such as a signing adapter of earlier
243
+ * releases, which deploy refuses rather than deploy unsigned.
244
+ */
245
+ type BundleSigningState = {
246
+ readonly status: "on";
247
+ readonly key: {
248
+ readonly secret: string;
249
+ } | {
250
+ readonly privateKeyPath: string;
251
+ };
252
+ } | {
253
+ readonly status: "off";
254
+ } | {
255
+ readonly status: "unsigned";
256
+ } | {
257
+ readonly status: "invalid";
258
+ readonly message: string;
259
+ };
260
+ declare const readBundleSigningState: (signing: unknown) => BundleSigningState;
261
+ /** The `secret()` the config's `signing` reads its private key from, if any. */
262
+ declare const bundleSigningSecretRef: (signing: unknown) => SecretRef | undefined;
263
+ /**
264
+ * A bundle signing failure whose message the CLI prints as it is: it names
265
+ * the secret and the next step, and quotes no key material.
266
+ */
267
+ declare class BundleSigningKeyError extends Error {
268
+ constructor(message: string, options?: ErrorOptions);
269
+ }
199
270
  interface BundleSigningSession {
200
- readonly name: string;
201
271
  readonly publicKey: string;
202
272
  readonly signFileHash: (fileHash: string) => Promise<string>;
203
273
  }
204
274
  declare const readBundleSigningPublicKeyFile: (publicKeyPath: string, options?: {
205
275
  readonly cwd?: string;
206
276
  }) => Promise<string>;
207
- declare const prepareBundleSigning: (signing: SigningConfig | undefined, options?: {
208
- readonly cwd?: string;
209
- }) => Promise<BundleSigningSession | null>;
210
- /** Resolves the public identity of the configured bundle signer. */
211
- declare const getBundleSigningPublicKey: (signing: SigningConfig | undefined, options?: {
277
+ interface BundleSigningOptions {
212
278
  readonly cwd?: string;
213
- }) => Promise<string | null>;
279
+ /** The config's `secrets` adapter; the configured one by default. */
280
+ readonly secrets?: SecretsAdapter;
281
+ }
282
+ /**
283
+ * Prepares the run's bundle signing: the public key the app must embed, and
284
+ * a signer of SHA-256 file hashes that signs each hash once. Null when
285
+ * `signing` is omitted or `{ enabled: false }`.
286
+ */
287
+ declare const prepareBundleSigning: (signing: unknown, options?: BundleSigningOptions) => Promise<BundleSigningSession | null>;
288
+ /**
289
+ * The public key of the configured bundle signing key, in SPKI PEM; null
290
+ * when `signing` signs nothing.
291
+ */
292
+ declare const getBundleSigningPublicKey: (signing: unknown, options?: BundleSigningOptions) => Promise<string | null>;
214
293
  //#endregion
215
294
  //#region src/ConfigBuilder.d.ts
216
295
  type BuildType = "bare" | "rock" | "expo";
@@ -364,8 +443,8 @@ declare const CREDENTIAL_ENV_NAMES: {
364
443
  //#endregion
365
444
  //#region src/credentialResolver.d.ts
366
445
  /**
367
- * The build credentials the CLI resolves by name. Deploy credentials reach
368
- * the config's adapters through `secretEnv`.
446
+ * The build credentials the CLI resolves by name. Adapter credentials are
447
+ * `secret()`s the adapters call.
369
448
  */
370
449
  interface Credentials {
371
450
  /** App Store Connect API key, for automatic signing and uploads. */
@@ -411,30 +490,41 @@ interface CredentialResolver {
411
490
  */
412
491
  dispose(): Promise<void>;
413
492
  }
493
+ /**
494
+ * A command to print, broken at spaces with ` \` once a line would pass
495
+ * 74 columns, each continuation indented two spaces, so a terminal never
496
+ * wraps it mid-word and it still pastes as one command.
497
+ */
498
+ declare const formatCommand: (command: string) => string;
414
499
  /** The credentials Hot Updater issues itself after a sign-in. */
415
- type IssuedCredentialKind = Exclude<CredentialKind, "android-keystore">;
500
+ type IssuedCredentialKind = "asc-api-key";
501
+ /** The credentials `secrets put <name> <file>` stores from one file. */
502
+ type FileCredentialKind = Exclude<CredentialKind, IssuedCredentialKind>;
503
+ /**
504
+ * The command that stores the file you have as `name`: the service
505
+ * account's JSON key, or the app's upload keystore. `--kind` is named only
506
+ * for a name that is not the kind.
507
+ */
508
+ declare const credentialPutCommand: (kind: FileCredentialKind, name?: string) => string;
416
509
  /**
417
510
  * The command that stores the key Hot Updater issues as `name`: an App
418
- * Store Connect API key after an Apple Account sign-in, a Play service
419
- * account after a Google one, and an upload keystore it creates.
511
+ * Store Connect API key after an Apple Account sign-in, and an upload
512
+ * keystore it creates.
420
513
  */
421
514
  declare const credentialIssueCommand: (kind: CredentialKind, name?: string) => string;
422
515
  /** The command group of each issued kind's shortcut, `<group> login`. */
423
516
  declare const CREDENTIAL_LOGIN_GROUPS: {
424
517
  readonly "asc-api-key": "apple";
425
- readonly "play-service-account": "google-play";
426
518
  };
427
519
  /**
428
520
  * The command people meet first that issues `kind` as `name`: its shortcut,
429
- * `apple login` for an App Store Connect API key or `google-play login`
430
- * for a Play service account, which takes nothing and stores the kind's
431
- * own name; for another name, `credentialIssueCommand`.
521
+ * `apple login` for an App Store Connect API key, which takes nothing and
522
+ * stores the kind's own name; for another name, `credentialIssueCommand`.
432
523
  */
433
524
  declare const credentialLoginCommand: (kind: IssuedCredentialKind, name?: string) => string;
434
525
  /**
435
526
  * The command that stores a missing credential of `kind` as `name`: the
436
- * upload keystore Hot Updater creates, or the key it issues after a
437
- * sign-in.
527
+ * key Hot Updater issues after an Apple sign-in, or the file you have.
438
528
  */
439
529
  declare const credentialStoreCommand: (kind: CredentialKind, name?: string) => string;
440
530
  declare class CredentialUnavailableError extends Error {
@@ -565,15 +655,6 @@ type WriteHotUpdaterConfigResult = {
565
655
  path: string;
566
656
  reason?: string;
567
657
  };
568
- /**
569
- * `const <name> = secretEnv([...names])`, a helper a managed config reads
570
- * credentials with: from the environment and `.env.hotupdater` first, then
571
- * from the config's `secrets` adapter. `storageSecrets` and
572
- * `databaseSecrets` read each adapter's own, so a command that reaches only
573
- * one needs only its credentials; `deploySecrets` reads what both share.
574
- * Its builder imports `secretEnv` from `hot-updater`.
575
- */
576
- declare const secretEnvHelper: (name: "databaseSecrets" | "deploySecrets" | "storageSecrets", names: readonly string[]) => ManagedHelperStatement;
577
658
  declare const createHotUpdaterConfigScaffold: ({ build, storage, database, plugins, extraImports, helperStatements, updateStrategy }: CreateHotUpdaterConfigScaffoldOptions) => HotUpdaterConfigScaffold;
578
659
  declare const createHotUpdaterConfigScaffoldFromBuilder: (builder: ConfigBuilder, { helperStatements, updateStrategy }?: CreateHotUpdaterConfigScaffoldFromBuilderOptions) => HotUpdaterConfigScaffold;
579
660
  /**
@@ -581,6 +662,14 @@ declare const createHotUpdaterConfigScaffoldFromBuilder: (builder: ConfigBuilder
581
662
  * existing config with the scaffold's build, storage, database, plugins, and
582
663
  * helpers merged in, keeping the project's own settings.
583
664
  */
665
+ /**
666
+ * Whether `hot-updater.config.ts` in `cwd` sets a team `secrets` adapter,
667
+ * read from its text: a `secrets` property other than `localSecrets(...)`,
668
+ * or a config whose shape init can't read. False without the file. Init
669
+ * reads the store through the loaded config, so one that sets a store but
670
+ * doesn't load must be fixed first.
671
+ */
672
+ declare const configSetsTeamSecrets: (cwd: string) => Promise<boolean>;
584
673
  declare const writeHotUpdaterConfig: (scaffold: HotUpdaterConfigScaffold, filePath?: string) => Promise<WriteHotUpdaterConfigResult>;
585
674
  /**
586
675
  * Writes hot-updater.config.ts and says what it did. `settings` names the
@@ -593,6 +682,30 @@ declare const writeHotUpdaterFiles: (scaffold: HotUpdaterConfigScaffold, { cwd,
593
682
  }) => Promise<{
594
683
  readonly config: WriteHotUpdaterConfigResult;
595
684
  }>;
685
+ /** What `addSigningSecretToConfigText` did. */
686
+ type AddSigningSecretResult = {
687
+ readonly status: "added";
688
+ readonly text: string;
689
+ } |
690
+ /** The config already sets `signing`, which stays as it is. */
691
+ {
692
+ readonly status: "kept";
693
+ } |
694
+ /** The file is no `export default defineConfig({ ... })` it can edit. */
695
+ {
696
+ readonly status: "unsupported";
697
+ };
698
+ /**
699
+ * The config text with `signing: secret("<name>")` added, and `secret` in
700
+ * its `hot-updater` import, once. A config that sets `signing` in any form,
701
+ * such as 1.1's `{ enabled: true, privateKeyPath }`, is kept.
702
+ */
703
+ declare const addSigningSecretToConfigText: (text: string, name: string) => AddSigningSecretResult;
704
+ /**
705
+ * Adds `signing: secret("<name>")` to `hot-updater.config.ts` in `cwd`, as
706
+ * `addSigningSecretToConfigText` does. Without the file, nothing is written.
707
+ */
708
+ declare const addSigningSecretToConfig: (cwd: string, name: string) => Promise<AddSigningSecretResult["status"] | "missing">;
596
709
  //#endregion
597
710
  //#region src/hotUpdaterEnv.d.ts
598
711
  type HotUpdaterInitEnv = {
@@ -685,7 +798,7 @@ type InitProviderDefinition<TInputs extends InitProviderInputsDefinition = InitP
685
798
  readonly label: string;
686
799
  /**
687
800
  * The variables of the credentials the config init writes reads with
688
- * `secretEnv`, such as an API token. With a team `secrets` adapter, init
801
+ * `secret()`, such as an API token. With a team `secrets` adapter, init
689
802
  * stores them there with the app's API key, and reads one the
690
803
  * environment and the env file lack from it.
691
804
  */
@@ -902,6 +1015,8 @@ declare const reactNativeCliFingerprint: (cwd: string, options: NativeFingerprin
902
1015
  type HotUpdaterLogWriter = {
903
1016
  logFilePath: string | null;
904
1017
  writeStream: (input: Readable) => Promise<void>;
1018
+ /** Writes lines of its own, such as the command a build runs. */
1019
+ writeLines: (lines: readonly string[]) => void;
905
1020
  writeError: (error: unknown) => void;
906
1021
  close: () => Promise<void>;
907
1022
  };
@@ -911,17 +1026,6 @@ declare const createLogWriter: ({ prefix, logFilePath }: {
911
1026
  logFilePath?: string;
912
1027
  }) => Promise<HotUpdaterLogWriter>;
913
1028
  //#endregion
914
- //#region src/localBundleSigning.d.ts
915
- /** The secret `keys generate --secret` stores the private key as by default. */
916
- declare const DEFAULT_SIGNING_KEY_SECRET = "bundle-signing-key";
917
- /** Local signing enabled, with its private key from a file or a secret. */
918
- type EnabledLocalSigningConfig = Extract<LocalSigningConfig, {
919
- enabled: true;
920
- }>;
921
- declare const normalizeSigningConfig: (signing: SigningConfig | undefined, { secrets }?: {
922
- readonly secrets?: SecretsAdapter;
923
- }) => BundleSigningAdapter | EnabledLocalSigningConfig | undefined;
924
- //#endregion
925
1029
  //#region src/loadConfig.d.ts
926
1030
  type HotUpdaterConfigOptions = {
927
1031
  platform: Platform;
@@ -934,9 +1038,14 @@ type ConfigResponse = RequiredDeep<Omit<ConfigInput, "database" | "storage" | "p
934
1038
  storage?: StorageAdapter;
935
1039
  /** The plugins the server runs; none when the config lists none. */
936
1040
  plugins: readonly AnyHotUpdaterPlugin[];
937
- signing?: ReturnType<typeof normalizeSigningConfig>;
938
1041
  /**
939
- * Where `secret:` references and issued keys are read and stored: the
1042
+ * As the config sets it, read only when a command signs: deploy refuses a
1043
+ * value it doesn't take (`readBundleSigningState`), and other commands,
1044
+ * such as the `secrets put` that fixes it, still load the config.
1045
+ */
1046
+ signing?: SigningConfig;
1047
+ /**
1048
+ * Where `secret()` references and issued keys are read and stored: the
940
1049
  * config's adapter alone, or `localSecrets()` when it sets none
941
1050
  * (`resolveSecretsAdapter`).
942
1051
  */
@@ -956,10 +1065,12 @@ declare const loadPlatformConfigs: <TPlatform extends Platform>(platforms: reado
956
1065
  readonly config: ConfigResponse;
957
1066
  }[]>;
958
1067
  /**
959
- * The names every `secretEnv` the config created while it loaded reads,
960
- * such as `HOT_UPDATER_CLOUDFLARE_API_TOKEN`, in the order it created them.
1068
+ * The names the config's `secret()`s reference for its adapters, such as
1069
+ * `HOT_UPDATER_CLOUDFLARE_API_TOKEN`, in the order the config created
1070
+ * them: every name but those of build credentials, which `doctor` lists
1071
+ * by field.
961
1072
  */
962
- declare const getSecretEnvNames: (config: ConfigResponse) => readonly string[];
1073
+ declare const getDeploySecretNames: (config: ConfigResponse) => readonly string[];
963
1074
  //#endregion
964
1075
  //#region src/serverDefinition.d.ts
965
1076
  /** A plugin's endpoint on a server's `handlers.client`. */
@@ -2326,7 +2437,7 @@ declare const readPackageUp: <T = unknown>(cwd: string) => Promise<ReadPackageUp
2326
2437
  * interpreter reads (`NODE_*` but `NODE_ENV`, `PATH`, `LD_*`, `DYLD_*`,
2327
2438
  * `BASH_ENV`, `ENV`, `GIT_*`, `npm_config_*`, the JVM's, Gradle's, Ruby's,
2328
2439
  * Python's, and Perl's options), or one Hot Updater reads its credentials
2329
- * from. `secretEnv` refuses these names, and so does every environment the
2440
+ * from. `secret()` refuses these names, and so does every environment the
2330
2441
  * CLI gives a child process from resolved secrets.
2331
2442
  */
2332
2443
  declare const isReservedVariableName: (name: string) => boolean;
@@ -2416,14 +2527,16 @@ declare const readLocalKey: (name: string, cwd: string) => Promise<string | unde
2416
2527
  declare const writeLocalKey: (name: string, value: string, cwd: string) => Promise<string>;
2417
2528
  //#endregion
2418
2529
  //#region src/secrets.d.ts
2419
- /** Whether `name` is a secret's name, as `secret:<name>` takes one. */
2530
+ /** Whether `name` is a secret's name, as `secret("<name>")` takes one. */
2420
2531
  declare const isSecretName: (name: string) => boolean;
2532
+ /** Whether `value` is a `secret("<name>")` reference. */
2533
+ declare const isSecretRef: (value: unknown) => value is SecretRef;
2421
2534
  /**
2422
- * The secret name a config's `secret:<name>` reference names, such as
2423
- * `release-keystore` for `"secret:release-keystore"`. `field` is the config
2424
- * field the reference is in, which the error names.
2535
+ * The secret name a config's `secret("<name>")` names, such as
2536
+ * `release-keystore` for `secret("release-keystore")`. `field` is the
2537
+ * config field it is in, which the error names.
2425
2538
  */
2426
- declare const parseSecretReference: (reference: string, field: string) => string;
2539
+ declare const parseSecretReference: (reference: unknown, field: string) => string;
2427
2540
  /**
2428
2541
  * The environment variable the default store reads a secret from: a name
2429
2542
  * that is a variable name already, such as `CLOUDFLARE_API_TOKEN`, as it
@@ -2475,8 +2588,8 @@ declare const resolveSecretsAdapter: (configured?: SecretsAdapter) => SecretsAda
2475
2588
  declare const getLocalSecretsStore: (secrets: SecretsAdapter) => LocalSecretsStore | undefined;
2476
2589
  /**
2477
2590
  * The config's own `secrets` adapter: undefined for `localSecrets()`,
2478
- * which is the adapter when the config sets none. `secretEnv` reads deploy
2479
- * credentials from it.
2591
+ * which is the adapter when the config sets none. A called `secret()` reads
2592
+ * from it.
2480
2593
  */
2481
2594
  declare const getConfiguredAdapter: (secrets: SecretsAdapter) => SecretsAdapter | undefined;
2482
2595
  /**
@@ -2501,23 +2614,30 @@ declare const readSecretWithSource: (secrets: SecretsAdapter, name: string, cwd:
2501
2614
  declare const keepsKeysOnThisMachine: (secrets: SecretsAdapter) => boolean;
2502
2615
  /**
2503
2616
  * The `secrets` adapter of one config load, filled once the config it
2504
- * evaluates resolves: each `secretEnv` the evaluation creates reads from it,
2505
- * and adds the names it reads to `names`.
2617
+ * evaluates resolves: each `secret()` the evaluation creates reads from it,
2618
+ * and adds its name to `names`.
2506
2619
  */
2507
2620
  interface SecretsScope {
2508
2621
  secrets?: SecretsAdapter;
2509
2622
  names?: Set<string>;
2623
+ /**
2624
+ * The names build credentials reference, such as `signing.keystore`'s,
2625
+ * which the CLI reads for their kind: the batched read leaves them out.
2626
+ */
2627
+ buildNames?: Set<string>;
2628
+ /** The one read of the scope's other names, once a `secret()` is called. */
2629
+ read?: Promise<Readonly<Record<string, string | undefined>>>;
2510
2630
  }
2511
2631
  /**
2512
2632
  * Evaluates a config, the file or a config function, with `scope` as the
2513
- * scope of every `secretEnv` it creates, so each reads the `secrets` of the
2633
+ * scope of every `secret()` it creates, so each reads the `secrets` of the
2514
2634
  * config that created it, whatever config loads after. It is kept on
2515
2635
  * `globalThis`: the config file loads its own copy of Hot Updater's modules.
2516
2636
  */
2517
2637
  declare const withSecretsScope: <T>(scope: SecretsScope, evaluate: () => Promise<T> | T) => Promise<T>;
2518
2638
  /**
2519
2639
  * Makes `secrets` the adapter a credential resolver reads from by default,
2520
- * and a `secretEnv` created outside any config load, as `loadConfig` does
2640
+ * and a `secret()` created outside any config load, as `loadConfig` does
2521
2641
  * with the config's. It is kept on `globalThis`: the config file loads Hot
2522
2642
  * Updater's modules again, as its own copies.
2523
2643
  */
@@ -2536,29 +2656,96 @@ declare const readSecrets: (secrets: SecretsAdapter, names: readonly string[], c
2536
2656
  /** Where an adapter keeps `name`, for messages. */
2537
2657
  declare const describeSecret: (secrets: SecretsAdapter, name: string) => string;
2538
2658
  /**
2539
- * Environment variables from the `secrets` adapter of the config that
2540
- * creates it, as a function a config calls when an adapter needs them, so loading
2541
- * `hot-updater.config.ts` reads no secret. Each name set in the environment
2542
- * or `.env.hotupdater` wins; the others are read from the config's
2543
- * `secrets` adapter in one call, and without one they must be set. The values go only to the caller: they are never set in
2544
- * `process.env`, and are masked in the CLI's logs. Names a loader or
2545
- * interpreter reads, such as `NODE_OPTIONS`, are refused.
2659
+ * `secret("<name>")`: the secret `name` in `hot-updater.config.ts`, for a
2660
+ * build credential, such as `signing.keystore`, or any adapter credential,
2661
+ * which calls it on first use, so loading the config reads no secret.
2662
+ * Called, it reads `name`'s variable (`secretVariableName`) in the
2663
+ * environment or `.env.hotupdater`, else the config's `secrets` adapter:
2664
+ * the first call reads every name the config's `secret()`s reference and
2665
+ * the environment doesn't set, in one `get`. With `localSecrets()`, the
2666
+ * variable must be set: its files hold only the keys Hot Updater stores.
2667
+ * Values are masked in the CLI's logs and never set in `process.env`.
2668
+ * Names a loader or interpreter reads, such as `NODE_OPTIONS`, are refused.
2669
+ * A server passes its own environment's values instead.
2546
2670
  *
2547
2671
  * @example
2548
- * const deploy = secretEnv(["S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY"]);
2549
- * s3Storage({
2672
+ * r2Storage({
2550
2673
  * bucketName: "bundles",
2551
- * region: "us-east-1",
2552
- * credentials: async () => {
2553
- * const env = await deploy();
2554
- * return {
2555
- * accessKeyId: env.S3_ACCESS_KEY_ID,
2556
- * secretAccessKey: env.S3_SECRET_ACCESS_KEY,
2557
- * };
2674
+ * accountId: "<account-id>",
2675
+ * credentials: {
2676
+ * accessKeyId: secret("HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID"),
2677
+ * secretAccessKey: secret("HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"),
2558
2678
  * },
2559
2679
  * });
2560
2680
  */
2561
- declare const secretEnv: <const TName extends string>(names: readonly TName[]) => (() => Promise<Readonly<Record<TName, string>>>);
2681
+ declare const secret: (name: string) => SecretRef;
2682
+ //#endregion
2683
+ //#region src/step.d.ts
2684
+ type Output = Writable & {
2685
+ isTTY?: boolean;
2686
+ columns?: number;
2687
+ };
2688
+ /** `4.2s`, `38s`, `6m41s`, `1h02m`. */
2689
+ declare const formatDuration: (ms: number) => string;
2690
+ /**
2691
+ * `message` with `duration` at the right edge of a step's line, the message
2692
+ * cut with `…` when the line would be wider.
2693
+ */
2694
+ declare const withDuration: (message: string, ms: number, width?: number) => string;
2695
+ /** `text` cut to `width` visible columns, with `…` for the rest. */
2696
+ declare const truncateLine: (text: string, width: number) => string;
2697
+ /** How a finished step's line is marked. */
2698
+ type StepLevel = "step" | "info" | "warn";
2699
+ /**
2700
+ * A step of a command that takes a while, shown as one line: at a terminal,
2701
+ * a spinner whose line shows the step's current detail and its elapsed
2702
+ * time, which ends as the step's line with its duration; elsewhere, such as
2703
+ * in CI, only that last line.
2704
+ *
2705
+ * While it runs, what other code prints through `p` is held: a spinner's
2706
+ * messages become the step's detail, and logs print after the step's line,
2707
+ * but an error ends the step as failed first and prints at once, since the
2708
+ * process may exit right after it.
2709
+ */
2710
+ interface Step {
2711
+ /** Starts the step, once: nothing shows before. */
2712
+ start(): Step;
2713
+ /** Shows `detail` after the title on the live line, or the title alone. */
2714
+ update(detail?: string): void;
2715
+ /**
2716
+ * Ends the step with `message`, the title by default, and its duration,
2717
+ * marked as a finished step or with `level`.
2718
+ */
2719
+ succeed(message?: string, options?: {
2720
+ level?: StepLevel;
2721
+ }): void;
2722
+ /** Ends the step as failed, with `message` or `<title> failed`. */
2723
+ fail(message?: string): void;
2724
+ /** Milliseconds since it started, or 0 before. */
2725
+ readonly elapsedMs: number;
2726
+ /** Whether it started and has not ended. */
2727
+ readonly active: boolean;
2728
+ }
2729
+ interface StepOptions {
2730
+ output?: Output;
2731
+ }
2732
+ /**
2733
+ * A step that shows nothing until `start()`. A step created while another
2734
+ * runs is part of it: its title and detail become the running step's detail.
2735
+ */
2736
+ declare const createStep: (title: string, { output }?: StepOptions) => Step;
2737
+ /**
2738
+ * Ends the running step as failed, if one runs, before a command prints
2739
+ * its error.
2740
+ */
2741
+ declare const failActiveStep: () => void;
2742
+ /** A step, started. */
2743
+ declare const startStep: (title: string, options?: StepOptions) => Step;
2744
+ /**
2745
+ * Runs `run` as a step titled `title`, which ends with `done(result)`, or as
2746
+ * failed when `run` throws.
2747
+ */
2748
+ declare const withStep: <T>(title: string, run: (step: Step) => Promise<T>, done?: (result: T) => string, options?: StepOptions) => Promise<T>;
2562
2749
  //#endregion
2563
2750
  //#region src/teamSecrets.d.ts
2564
2751
  /**
@@ -2618,4 +2805,4 @@ type TransformTemplateArgs<T extends string> = { [Key in ExtractPlaceholders<T>]
2618
2805
  */
2619
2806
  declare function transformTemplate<T extends string>(templateString: T, values: TransformTemplateArgs<T>): string;
2620
2807
  //#endregion
2621
- export { AppClientCredential, AppClientPlugin, AssembleServerOptions, AssembledServer, BuildFailedError, BuildFailureSummaryConfig, BuildLogger, BuildLoggerConfig, BuildType, BundleSigningSession, CREDENTIAL_ENV_NAMES, CREDENTIAL_LOGIN_GROUPS, ClientAuthSpec, ClientCredentialSpec, ConfigBuilder, ConfigBuilderScaffold, ConfigResponse, CreateCredentialResolverOptions, CreateHotUpdaterConfigScaffoldFromBuilderOptions, CreateHotUpdaterConfigScaffoldOptions, type CredentialFiles, CredentialKind, CredentialRequest, CredentialResolver, CredentialUnavailableError, Credentials, DEFAULT_SIGNING_KEY_SECRET, HOT_UPDATER_HOME_ENV, HOT_UPDATER_SERVER_PACKAGE_VERSION_ENV, HotUpdateDirUtil, HotUpdaterConfigOptions, HotUpdaterConfigScaffold, HotUpdaterInitEnv, HotUpdaterLogWriter, INTERFACE_FINGERPRINT_ENGINE, ImportInfo, InitEnvFileError, InitError, InitProviderDefinition, InitProviderInputDefinition, InitProviderInputPersistence, IssuedCredentialKind, LOCAL_SECRETS_NAME, LegacyInfrastructureError, LocalSecretsOptions, LocalSecretsStore, MANAGED_CLIENT_CREDENTIAL_ENV, ManagedHelperStatement, ManagedHelperStrategy, MissingInitInputsError, NativeDependency, NativeInterface, PromptProgress, PromptSpinner, ProviderConfig, ProvisionedClientCredential, ReactNativeMetadata, ReadPackageUpResult, RunInitOptions, SecretsScope, ServerClientEndpoint, ServerDefinition, ServerDefinitionError, WriteHotUpdaterConfigResult, assembleServer, assertInfrastructureGenerationAtUrl, assertInfrastructureGenerationPayload, assertInitInputs, assertInitProviderInputs, assertUnreservedEnv, autolinkingConfigCommand, banner, clientAuthOf, typedColors as colors, confirmInitInputPersistence, copyDirToTmp, createCredentialResolver, createHotUpdaterConfigScaffold, createHotUpdaterConfigScaffoldFromBuilder, createInterfaceFingerprint, createLocalSecretsStore, createLogWriter, createMigrator, createMinBundleId, createTarBrTargetFiles, createZip, credentialIssueCommand, credentialLoginCommand, credentialStoreCommand, decryptJson, defineInitProvider, describeSecret, describeStoredSecret, encryptJson, ensureInstallPackages, generateClientCredential, generateSchema, generatesSchema, getAndroidSdkPath, getBundleSigningPublicKey, getConfiguredAdapter, getConfiguredSecrets, getCwd, getHotUpdaterEnvValue, getHotUpdaterHome, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, getLocalKeyFile, getLocalKeyStoreDir, getLocalSecretsStore, getMissingInitInputs, getMissingInitProviderInputs, getPackageManager, getProjectKey, getReactNativeMetadatas, getSecretEnvNames, getStorageFileByteSize, isCI, isCodegenSpecFile, isReservedVariableName, isSecretName, isServerDefinition, keepsKeysOnThisMachine, link, loadConfig, loadPlatformConfigs, loadTeamSecrets, localSecrets, log, makeEnv, maskSecretValues, moduleSpecifiersOf, nonInteractiveReason, p, parseLoadedEnv, parseSecretReference, prepareBundleSigning, printAppSetup, printBanner, provisionClientCredential, putStorageFile, reactNativeCliFingerprint, reactNativeConfigCommand, readBundleSigningPublicKeyFile, readHotUpdaterInitEnv, readLoadedEnvFile, readLoadedHotUpdaterEnv, readLocalKey, readMissingFromTeamSecrets, readPackageUp, readReactNativeInterface, readSecretVariables, readSecretWithSource, readSecrets, registerCredentialValue, registerSecretValue, renderAppImports, renderAppSetup, renderImportStatements, resolveExpoAutolinking, resolveHotUpdaterServerVersion, resolveInitProviderInput, resolveInitProviderInputs, resolveLocalSecretsPath, resolvePackageVersion, resolveSecretsAdapter, secretEnv, secretEnvHelper, secretVariableName, serverDefinitionOf, setConfiguredSecrets, shouldAutoSelectOnlyInitResource, storeEnvFileSecrets, stripAnsi, transformEnv, transformTemplate, withCredentialResolver, withSecretsScope, writeHotUpdaterConfig, writeHotUpdaterFiles, writeLocalKey };
2808
+ export { AddSigningSecretResult, AppClientCredential, AppClientPlugin, AssembleServerOptions, AssembledServer, BUNDLE_SIGNING_KEY_SECRET, BuildFailedError, BuildFailureSummaryConfig, BuildLogger, BuildLoggerConfig, BuildPhaseReader, BuildType, BundleSigningKeyError, BundleSigningOptions, BundleSigningSession, BundleSigningState, CREDENTIAL_ENV_NAMES, CREDENTIAL_LOGIN_GROUPS, ClientAuthSpec, ClientCredentialSpec, ConfigBuilder, ConfigBuilderScaffold, ConfigResponse, CreateCredentialResolverOptions, CreateHotUpdaterConfigScaffoldFromBuilderOptions, CreateHotUpdaterConfigScaffoldOptions, type CredentialFiles, CredentialKind, CredentialRequest, CredentialResolver, CredentialUnavailableError, Credentials, FileCredentialKind, HOT_UPDATER_HOME_ENV, HOT_UPDATER_SERVER_PACKAGE_VERSION_ENV, HotUpdateDirUtil, HotUpdaterConfigOptions, HotUpdaterConfigScaffold, HotUpdaterInitEnv, HotUpdaterLogWriter, INTERFACE_FINGERPRINT_ENGINE, INVALID_SIGNING_MESSAGE, INVALID_SIGNING_NEXT_STEP, ISSUE_SIGNING_KEY_COMMAND, ImportInfo, InitEnvFileError, InitError, InitProviderDefinition, InitProviderInputDefinition, InitProviderInputPersistence, IssuedCredentialKind, LOCAL_SECRETS_NAME, LegacyInfrastructureError, LocalSecretsOptions, LocalSecretsStore, MANAGED_CLIENT_CREDENTIAL_ENV, ManagedHelperStatement, ManagedHelperStrategy, MissingInitInputsError, NativeDependency, NativeInterface, PUT_SIGNING_KEY_COMMAND, PromptProgress, PromptSpinner, ProviderConfig, ProvisionedClientCredential, ReactNativeMetadata, ReadPackageUpResult, RunInitOptions, SecretsScope, ServerClientEndpoint, ServerDefinition, ServerDefinitionError, Step, StepLevel, UNSIGNED_BUNDLES_NEXT_STEP, UNSIGNED_BUNDLES_WARNING, WriteHotUpdaterConfigResult, addSigningSecretToConfig, addSigningSecretToConfigText, assembleServer, assertInfrastructureGenerationAtUrl, assertInfrastructureGenerationPayload, assertInitInputs, assertInitProviderInputs, assertUnreservedEnv, autolinkingConfigCommand, banner, bundleSigningSecretRef, clientAuthOf, typedColors as colors, configSetsTeamSecrets, confirmInitInputPersistence, copyDirToTmp, createCredentialResolver, createHotUpdaterConfigScaffold, createHotUpdaterConfigScaffoldFromBuilder, createInterfaceFingerprint, createLocalSecretsStore, createLogWriter, createMigrator, createMinBundleId, createStep, createTarBrTargetFiles, createZip, credentialIssueCommand, credentialLoginCommand, credentialPutCommand, credentialStoreCommand, decryptJson, defineInitProvider, describeSecret, describeStoredSecret, encryptJson, ensureInstallPackages, failActiveStep, formatCommand, formatDuration, generateClientCredential, generateSchema, generatesSchema, getAndroidSdkPath, getBundleSigningPublicKey, getConfiguredAdapter, getConfiguredSecrets, getCwd, getDeploySecretNames, getHotUpdaterEnvValue, getHotUpdaterHome, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, getLocalKeyFile, getLocalKeyStoreDir, getLocalSecretsStore, getMissingInitInputs, getMissingInitProviderInputs, getPackageManager, getProjectKey, getReactNativeMetadatas, getStorageFileByteSize, isCI, isCodegenSpecFile, isReservedVariableName, isSecretName, isSecretRef, isServerDefinition, keepsKeysOnThisMachine, link, loadConfig, loadPlatformConfigs, loadTeamSecrets, localSecrets, log, makeEnv, maskSecretValues, moduleSpecifiersOf, nonInteractiveReason, p, parseLoadedEnv, parseSecretReference, prepareBundleSigning, printAppSetup, printBanner, provisionClientCredential, putStorageFile, reactNativeCliFingerprint, reactNativeConfigCommand, readBundleSigningPublicKeyFile, readBundleSigningState, readHotUpdaterInitEnv, readLoadedEnvFile, readLoadedHotUpdaterEnv, readLocalKey, readMissingFromTeamSecrets, readPackageUp, readReactNativeInterface, readSecretVariables, readSecretWithSource, readSecrets, registerCredentialValue, registerSecretValue, renderAppImports, renderAppSetup, renderImportStatements, resolveExpoAutolinking, resolveHotUpdaterServerVersion, resolveInitProviderInput, resolveInitProviderInputs, resolveLocalSecretsPath, resolvePackageVersion, resolveSecretsAdapter, secret, secretVariableName, serverDefinitionOf, setConfiguredSecrets, shouldAutoSelectOnlyInitResource, startStep, storeEnvFileSecrets, stripAnsi, transformEnv, transformTemplate, truncateLine, withCredentialResolver, withDuration, withSecretsScope, withStep, writeHotUpdaterConfig, writeHotUpdaterFiles, writeLocalKey };