@hot-updater/aws 1.2.0-rc.7 → 1.2.0-rc.8

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 CHANGED
@@ -315,10 +315,30 @@ async apply() {
315
315
  };
316
316
  };
317
317
  //#endregion
318
+ //#region src/lazyCredentials.ts
319
+ /**
320
+ * `credentials` as the AWS SDK takes them: access keys with a lazy field
321
+ * become a provider, which the SDK calls once, on its first request.
322
+ */
323
+ const toSdkCredentials = (credentials) => {
324
+ if (credentials === void 0 || typeof credentials === "function") return credentials;
325
+ const { accessKeyId, secretAccessKey, sessionToken, ...rest } = credentials;
326
+ if (typeof accessKeyId !== "function" && typeof secretAccessKey !== "function" && typeof sessionToken !== "function") return credentials;
327
+ return async () => ({
328
+ ...rest,
329
+ accessKeyId: await (0, _hot_updater_plugin_core.resolveLazy)(accessKeyId),
330
+ secretAccessKey: await (0, _hot_updater_plugin_core.resolveLazy)(secretAccessKey),
331
+ ...sessionToken === void 0 ? {} : { sessionToken: await (0, _hot_updater_plugin_core.resolveLazy)(sessionToken) }
332
+ });
333
+ };
334
+ //#endregion
318
335
  //#region src/dynamoDB.ts
319
336
  /** The DynamoDB client ignores the CloudFront and batching settings. */
320
- const adapterOf = ({ tableName, ...clientConfig }) => {
321
- const client = new _aws_sdk_client_dynamodb.DynamoDBClient(clientConfig);
337
+ const adapterOf = ({ tableName, credentials, ...clientConfig }) => {
338
+ const client = new _aws_sdk_client_dynamodb.DynamoDBClient({
339
+ ...clientConfig,
340
+ credentials: toSdkCredentials(credentials)
341
+ });
322
342
  const store = createDynamoDBStore({
323
343
  client,
324
344
  tableName
@@ -353,7 +373,10 @@ const marked = (target) => ({ [DATABASE_TARGET]: target });
353
373
  */
354
374
  const dynamoDB = (config) => {
355
375
  const { client, adapter } = adapterOf(config);
356
- const cloudFront = createUpdateRouteInvalidation(config);
376
+ const cloudFront = createUpdateRouteInvalidation({
377
+ ...config,
378
+ credentials: toSdkCredentials(config.credentials)
379
+ });
357
380
  return {
358
381
  ...(0, _hot_updater_plugin_core.createEngineDatabase)({
359
382
  name: "dynamoDB",
@@ -500,8 +523,11 @@ const cloudFrontDownloadUrl = (config) => {
500
523
  const PRESIGNED_URL_EXPIRES_IN_SECONDS = 3600;
501
524
  const isObjectNotFoundError = (error) => error instanceof Error && (error.name === "NotFound" || error.name === "NoSuchKey");
502
525
  function s3Storage(config) {
503
- const { bucketName, basePath, getDownloadUrl, ...s3Config } = config;
504
- const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig(s3Config));
526
+ const { bucketName, basePath, getDownloadUrl, credentials, ...s3Config } = config;
527
+ const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig({
528
+ ...s3Config,
529
+ credentials: toSdkCredentials(credentials)
530
+ }));
505
531
  const normalizedBasePath = basePath?.replace(/^\/+|\/+$/g, "") ?? "";
506
532
  const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(normalizedBasePath);
507
533
  const getListPrefix = (prefix = "") => {
package/dist/index.d.cts CHANGED
@@ -1,8 +1,24 @@
1
1
  import { DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
2
- import { EngineDatabase, PluginTables, SecretsAdapter, StorageAdapter, StorageAdapterWith } from "@hot-updater/plugin-core";
2
+ import { EngineDatabase, Lazy, PluginTables, SecretsAdapter, StorageAdapter, StorageAdapterWith } from "@hot-updater/plugin-core";
3
3
  import { S3ClientConfig } from "@aws-sdk/client-s3";
4
+ //#region src/lazyCredentials.d.ts
5
+ type SdkCredentials = S3ClientConfig["credentials"];
6
+ /**
7
+ * Access keys whose fields may each be a function that returns them, such
8
+ * as `secret("<name>")` in `hot-updater.config.ts`, called on first use.
9
+ */
10
+ interface LazyAwsCredentials {
11
+ readonly accessKeyId: Lazy<string>;
12
+ readonly secretAccessKey: Lazy<string>;
13
+ readonly sessionToken?: Lazy<string>;
14
+ }
15
+ /** The credentials the AWS SDK takes, or access keys with lazy fields. */
16
+ type AwsCredentialsOption = SdkCredentials | LazyAwsCredentials;
17
+ //#endregion
4
18
  //#region src/dynamoDB.d.ts
5
- interface DynamoDBConfig extends DynamoDBClientConfig {
19
+ interface DynamoDBConfig extends Omit<DynamoDBClientConfig, "credentials"> {
20
+ /** The SDK's credentials, or access keys whose fields are lazy. */
21
+ readonly credentials?: AwsCredentialsOption;
6
22
  readonly apiBasePath?: string;
7
23
  readonly cloudfrontDistributionId?: string;
8
24
  readonly shouldWaitForInvalidation?: boolean;
@@ -59,7 +75,9 @@ declare const cloudFrontDownloadUrl: (config: CloudFrontDownloadUrlOptions) => (
59
75
  }>;
60
76
  //#endregion
61
77
  //#region src/s3Storage.d.ts
62
- interface S3StorageConfig extends S3ClientConfig {
78
+ interface S3StorageConfig extends Omit<S3ClientConfig, "credentials"> {
79
+ /** The SDK's credentials, or access keys whose fields are lazy. */
80
+ credentials?: AwsCredentialsOption;
63
81
  bucketName: string;
64
82
  /** Base path where bundles will be stored in the bucket. */
65
83
  basePath?: string;
@@ -85,7 +103,7 @@ interface SecretsManagerOptions {
85
103
  /** The AWS region the secrets are in, such as `"us-east-1"`. */
86
104
  readonly region: string;
87
105
  /**
88
- * Put before every name to make its secret's name, so `secret:asc-api-key`
106
+ * Put before every name to make its secret's name, so `secret("asc-api-key")`
89
107
  * reads the secret `hot-updater/asc-api-key` and one IAM resource,
90
108
  * `secret:hot-updater/*`, covers them all. Letters, digits, and
91
109
  * `/_+=.@-`.
package/dist/index.d.mts CHANGED
@@ -1,8 +1,24 @@
1
1
  import { DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
2
- import { EngineDatabase, PluginTables, SecretsAdapter, StorageAdapter, StorageAdapterWith } from "@hot-updater/plugin-core";
2
+ import { EngineDatabase, Lazy, PluginTables, SecretsAdapter, StorageAdapter, StorageAdapterWith } from "@hot-updater/plugin-core";
3
3
  import { S3ClientConfig } from "@aws-sdk/client-s3";
4
+ //#region src/lazyCredentials.d.ts
5
+ type SdkCredentials = S3ClientConfig["credentials"];
6
+ /**
7
+ * Access keys whose fields may each be a function that returns them, such
8
+ * as `secret("<name>")` in `hot-updater.config.ts`, called on first use.
9
+ */
10
+ interface LazyAwsCredentials {
11
+ readonly accessKeyId: Lazy<string>;
12
+ readonly secretAccessKey: Lazy<string>;
13
+ readonly sessionToken?: Lazy<string>;
14
+ }
15
+ /** The credentials the AWS SDK takes, or access keys with lazy fields. */
16
+ type AwsCredentialsOption = SdkCredentials | LazyAwsCredentials;
17
+ //#endregion
4
18
  //#region src/dynamoDB.d.ts
5
- interface DynamoDBConfig extends DynamoDBClientConfig {
19
+ interface DynamoDBConfig extends Omit<DynamoDBClientConfig, "credentials"> {
20
+ /** The SDK's credentials, or access keys whose fields are lazy. */
21
+ readonly credentials?: AwsCredentialsOption;
6
22
  readonly apiBasePath?: string;
7
23
  readonly cloudfrontDistributionId?: string;
8
24
  readonly shouldWaitForInvalidation?: boolean;
@@ -59,7 +75,9 @@ declare const cloudFrontDownloadUrl: (config: CloudFrontDownloadUrlOptions) => (
59
75
  }>;
60
76
  //#endregion
61
77
  //#region src/s3Storage.d.ts
62
- interface S3StorageConfig extends S3ClientConfig {
78
+ interface S3StorageConfig extends Omit<S3ClientConfig, "credentials"> {
79
+ /** The SDK's credentials, or access keys whose fields are lazy. */
80
+ credentials?: AwsCredentialsOption;
63
81
  bucketName: string;
64
82
  /** Base path where bundles will be stored in the bucket. */
65
83
  basePath?: string;
@@ -85,7 +103,7 @@ interface SecretsManagerOptions {
85
103
  /** The AWS region the secrets are in, such as `"us-east-1"`. */
86
104
  readonly region: string;
87
105
  /**
88
- * Put before every name to make its secret's name, so `secret:asc-api-key`
106
+ * Put before every name to make its secret's name, so `secret("asc-api-key")`
89
107
  * reads the secret `hot-updater/asc-api-key` and one IAM resource,
90
108
  * `secret:hot-updater/*`, covers them all. Letters, digits, and
91
109
  * `/_+=.@-`.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CreateTableCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDBClient, UpdateTimeToLiveCommand, waitUntilTableExists } from "@aws-sdk/client-dynamodb";
2
- import { BUNDLE_STORAGE_PREFIX, CONTENT_ADDRESSED_ASSET_PREFIX, createEngineDatabase, createKvAdapter, createStorageAdapter, createStorageKeyBuilder, createStorageUri, migrateCoreSchema, parseStorageUri } from "@hot-updater/plugin-core";
2
+ import { BUNDLE_STORAGE_PREFIX, CONTENT_ADDRESSED_ASSET_PREFIX, createEngineDatabase, createKvAdapter, createStorageAdapter, createStorageKeyBuilder, createStorageUri, migrateCoreSchema, parseStorageUri, resolveLazy } from "@hot-updater/plugin-core";
3
3
  import { CloudFrontClient, CreateInvalidationCommand, GetInvalidationCommand } from "@aws-sdk/client-cloudfront";
4
4
  import { BatchGetCommand, BatchWriteCommand, DynamoDBDocumentClient, QueryCommand, TransactWriteCommand } from "@aws-sdk/lib-dynamodb";
5
5
  import { SSM } from "@aws-sdk/client-ssm";
@@ -314,10 +314,30 @@ async apply() {
314
314
  };
315
315
  };
316
316
  //#endregion
317
+ //#region src/lazyCredentials.ts
318
+ /**
319
+ * `credentials` as the AWS SDK takes them: access keys with a lazy field
320
+ * become a provider, which the SDK calls once, on its first request.
321
+ */
322
+ const toSdkCredentials = (credentials) => {
323
+ if (credentials === void 0 || typeof credentials === "function") return credentials;
324
+ const { accessKeyId, secretAccessKey, sessionToken, ...rest } = credentials;
325
+ if (typeof accessKeyId !== "function" && typeof secretAccessKey !== "function" && typeof sessionToken !== "function") return credentials;
326
+ return async () => ({
327
+ ...rest,
328
+ accessKeyId: await resolveLazy(accessKeyId),
329
+ secretAccessKey: await resolveLazy(secretAccessKey),
330
+ ...sessionToken === void 0 ? {} : { sessionToken: await resolveLazy(sessionToken) }
331
+ });
332
+ };
333
+ //#endregion
317
334
  //#region src/dynamoDB.ts
318
335
  /** The DynamoDB client ignores the CloudFront and batching settings. */
319
- const adapterOf = ({ tableName, ...clientConfig }) => {
320
- const client = new DynamoDBClient(clientConfig);
336
+ const adapterOf = ({ tableName, credentials, ...clientConfig }) => {
337
+ const client = new DynamoDBClient({
338
+ ...clientConfig,
339
+ credentials: toSdkCredentials(credentials)
340
+ });
321
341
  const store = createDynamoDBStore({
322
342
  client,
323
343
  tableName
@@ -352,7 +372,10 @@ const marked = (target) => ({ [DATABASE_TARGET]: target });
352
372
  */
353
373
  const dynamoDB = (config) => {
354
374
  const { client, adapter } = adapterOf(config);
355
- const cloudFront = createUpdateRouteInvalidation(config);
375
+ const cloudFront = createUpdateRouteInvalidation({
376
+ ...config,
377
+ credentials: toSdkCredentials(config.credentials)
378
+ });
356
379
  return {
357
380
  ...createEngineDatabase({
358
381
  name: "dynamoDB",
@@ -499,8 +522,11 @@ const cloudFrontDownloadUrl = (config) => {
499
522
  const PRESIGNED_URL_EXPIRES_IN_SECONDS = 3600;
500
523
  const isObjectNotFoundError = (error) => error instanceof Error && (error.name === "NotFound" || error.name === "NoSuchKey");
501
524
  function s3Storage(config) {
502
- const { bucketName, basePath, getDownloadUrl, ...s3Config } = config;
503
- const client = new S3Client(applyS3RuntimeAwsConfig(s3Config));
525
+ const { bucketName, basePath, getDownloadUrl, credentials, ...s3Config } = config;
526
+ const client = new S3Client(applyS3RuntimeAwsConfig({
527
+ ...s3Config,
528
+ credentials: toSdkCredentials(credentials)
529
+ }));
504
530
  const normalizedBasePath = basePath?.replace(/^\/+|\/+$/g, "") ?? "";
505
531
  const getStorageKey = createStorageKeyBuilder(normalizedBasePath);
506
532
  const getListPrefix = (prefix = "") => {
@@ -6579,10 +6579,30 @@ async apply() {
6579
6579
  };
6580
6580
  };
6581
6581
  //#endregion
6582
+ //#region src/lazyCredentials.ts
6583
+ /**
6584
+ * `credentials` as the AWS SDK takes them: access keys with a lazy field
6585
+ * become a provider, which the SDK calls once, on its first request.
6586
+ */
6587
+ const toSdkCredentials = (credentials) => {
6588
+ if (credentials === void 0 || typeof credentials === "function") return credentials;
6589
+ const { accessKeyId, secretAccessKey, sessionToken, ...rest } = credentials;
6590
+ if (typeof accessKeyId !== "function" && typeof secretAccessKey !== "function" && typeof sessionToken !== "function") return credentials;
6591
+ return async () => ({
6592
+ ...rest,
6593
+ accessKeyId: await (0, _hot_updater_plugin_core.resolveLazy)(accessKeyId),
6594
+ secretAccessKey: await (0, _hot_updater_plugin_core.resolveLazy)(secretAccessKey),
6595
+ ...sessionToken === void 0 ? {} : { sessionToken: await (0, _hot_updater_plugin_core.resolveLazy)(sessionToken) }
6596
+ });
6597
+ };
6598
+ //#endregion
6582
6599
  //#region src/dynamoDB.ts
6583
6600
  /** The DynamoDB client ignores the CloudFront and batching settings. */
6584
- const adapterOf = ({ tableName, ...clientConfig }) => {
6585
- const client = new _aws_sdk_client_dynamodb.DynamoDBClient(clientConfig);
6601
+ const adapterOf = ({ tableName, credentials, ...clientConfig }) => {
6602
+ const client = new _aws_sdk_client_dynamodb.DynamoDBClient({
6603
+ ...clientConfig,
6604
+ credentials: toSdkCredentials(credentials)
6605
+ });
6586
6606
  const store = createDynamoDBStore({
6587
6607
  client,
6588
6608
  tableName
@@ -6617,7 +6637,10 @@ const marked = (target) => ({ [DATABASE_TARGET]: target });
6617
6637
  */
6618
6638
  const dynamoDB = (config) => {
6619
6639
  const { client, adapter } = adapterOf(config);
6620
- const cloudFront = createUpdateRouteInvalidation(config);
6640
+ const cloudFront = createUpdateRouteInvalidation({
6641
+ ...config,
6642
+ credentials: toSdkCredentials(config.credentials)
6643
+ });
6621
6644
  return {
6622
6645
  ...(0, _hot_updater_plugin_core.createEngineDatabase)({
6623
6646
  name: "dynamoDB",
@@ -8419,10 +8442,11 @@ var SSMKeyPairManager = class {
8419
8442
  //#region iac/templates.ts
8420
8443
  /**
8421
8444
  * The config init writes. With the `resources` init set up, it names them,
8422
- * and an account's access keys are read with `secretEnv`, from the
8445
+ * and an account's access keys are read with `secret()`, from the
8423
8446
  * environment and `.env.hotupdater`, then the config's `secrets` adapter.
8424
- * Without them, as the agent scaffold writes it, it reads every value from
8425
- * the environment. A profile or SSO sign-in is each person's own.
8447
+ * Without them, as the agent scaffold writes it before the agent creates the
8448
+ * resources, it reads their names from the environment, where the agent
8449
+ * records them. A profile or SSO sign-in is each person's own.
8426
8450
  */
8427
8451
  const getConfigScaffold = (build, authMode, resources) => {
8428
8452
  const value = (envKey, resolved) => resolved === void 0 ? `process.env.${envKey}!` : JSON.stringify(resolved);
@@ -8478,31 +8502,19 @@ const awsOptions = {
8478
8502
  };`.trim()
8479
8503
  }];
8480
8504
  break;
8481
- case "account":
8482
- helperStatements = [{
8483
- name: "awsOptions",
8484
- strategy: "merge-object",
8485
- replaceIncompatibleProperties: ["credentials"],
8486
- code: resources === void 0 ? `
8505
+ case "account": helperStatements = [{
8506
+ name: "awsOptions",
8507
+ strategy: "merge-object",
8508
+ replaceIncompatibleProperties: ["credentials"],
8509
+ code: `
8487
8510
  const awsOptions = {
8488
8511
  region: ${region},
8489
8512
  credentials: {
8490
- accessKeyId: process.env.HOT_UPDATER_S3_ACCESS_KEY_ID!,
8491
- secretAccessKey: process.env.HOT_UPDATER_S3_SECRET_ACCESS_KEY!,
8492
- },
8493
- };`.trim() : `
8494
- const awsOptions = {
8495
- region: ${region},
8496
- credentials: async () => {
8497
- const env = await deploySecrets();
8498
- return {
8499
- accessKeyId: env.HOT_UPDATER_S3_ACCESS_KEY_ID,
8500
- secretAccessKey: env.HOT_UPDATER_S3_SECRET_ACCESS_KEY,
8501
- };
8513
+ accessKeyId: secret("HOT_UPDATER_S3_ACCESS_KEY_ID"),
8514
+ secretAccessKey: secret("HOT_UPDATER_S3_SECRET_ACCESS_KEY"),
8502
8515
  },
8503
8516
  };`.trim()
8504
- }];
8505
- if (resources !== void 0) helperStatements.unshift((0, _hot_updater_cli_tools.secretEnvHelper)("deploySecrets", ["HOT_UPDATER_S3_ACCESS_KEY_ID", "HOT_UPDATER_S3_SECRET_ACCESS_KEY"]));
8517
+ }];
8506
8518
  }
8507
8519
  const builder = new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setStorage(storageConfig).setDatabase(databaseConfig).setPlugins({
8508
8520
  imports: [{
@@ -8528,9 +8540,9 @@ const awsOptions = {
8528
8540
  named: [authMode.profile ? "fromIni" : "fromNodeProviderChain"]
8529
8541
  });
8530
8542
  break;
8531
- case "account": if (resources !== void 0) builder.addImport({
8543
+ case "account": builder.addImport({
8532
8544
  pkg: "hot-updater",
8533
- named: ["secretEnv"]
8545
+ named: ["secret"]
8534
8546
  });
8535
8547
  }
8536
8548
  return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(builder, { helperStatements });
@@ -1,5 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- import { ConfigBuilder, InitError, MissingInitInputsError, assembleServer, assertInfrastructureGenerationAtUrl, assertInfrastructureGenerationPayload, assertInitProviderInputs, colors, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, createZip, ensureInstallPackages, getCwd, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, p, printAppSetup, provisionClientCredential, readHotUpdaterInitEnv, resolveInitProviderInput, secretEnvHelper, transformEnv, writeHotUpdaterFiles } from "@hot-updater/cli-tools";
2
+ import { ConfigBuilder, InitError, MissingInitInputsError, assembleServer, assertInfrastructureGenerationAtUrl, assertInfrastructureGenerationPayload, assertInitProviderInputs, colors, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, createZip, ensureInstallPackages, getCwd, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, p, printAppSetup, provisionClientCredential, readHotUpdaterInitEnv, resolveInitProviderInput, transformEnv, writeHotUpdaterFiles } from "@hot-updater/cli-tools";
3
3
  import { apiKeys, insights, remoteConfig } from "@hot-updater/server/plugins";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
@@ -18,7 +18,7 @@ import { finished } from "node:stream/promises";
18
18
  import { Duplex, PassThrough, Readable, Transform, Writable, getDefaultHighWaterMark } from "node:stream";
19
19
  import { Buffer as Buffer$1 } from "node:buffer";
20
20
  import { CreateTableCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDB, DynamoDBClient, UpdateTimeToLiveCommand, waitUntilTableExists } from "@aws-sdk/client-dynamodb";
21
- import { SETTINGS_TABLE, aggregateBatchingTables, createEngineDatabase, createKvAdapter, encodeKvKey, migrateCoreSchema, toolingTargetOf } from "@hot-updater/plugin-core";
21
+ import { SETTINGS_TABLE, aggregateBatchingTables, createEngineDatabase, createKvAdapter, encodeKvKey, migrateCoreSchema, resolveLazy, toolingTargetOf } from "@hot-updater/plugin-core";
22
22
  import { CloudFront, CloudFrontClient, CreateInvalidationCommand, GetInvalidationCommand } from "@aws-sdk/client-cloudfront";
23
23
  import { BatchGetCommand, BatchWriteCommand, DynamoDBDocumentClient, QueryCommand, TransactWriteCommand } from "@aws-sdk/lib-dynamodb";
24
24
  import { fromIni, fromNodeProviderChain, fromSSO } from "@aws-sdk/credential-providers";
@@ -6574,10 +6574,30 @@ async apply() {
6574
6574
  };
6575
6575
  };
6576
6576
  //#endregion
6577
+ //#region src/lazyCredentials.ts
6578
+ /**
6579
+ * `credentials` as the AWS SDK takes them: access keys with a lazy field
6580
+ * become a provider, which the SDK calls once, on its first request.
6581
+ */
6582
+ const toSdkCredentials = (credentials) => {
6583
+ if (credentials === void 0 || typeof credentials === "function") return credentials;
6584
+ const { accessKeyId, secretAccessKey, sessionToken, ...rest } = credentials;
6585
+ if (typeof accessKeyId !== "function" && typeof secretAccessKey !== "function" && typeof sessionToken !== "function") return credentials;
6586
+ return async () => ({
6587
+ ...rest,
6588
+ accessKeyId: await resolveLazy(accessKeyId),
6589
+ secretAccessKey: await resolveLazy(secretAccessKey),
6590
+ ...sessionToken === void 0 ? {} : { sessionToken: await resolveLazy(sessionToken) }
6591
+ });
6592
+ };
6593
+ //#endregion
6577
6594
  //#region src/dynamoDB.ts
6578
6595
  /** The DynamoDB client ignores the CloudFront and batching settings. */
6579
- const adapterOf = ({ tableName, ...clientConfig }) => {
6580
- const client = new DynamoDBClient(clientConfig);
6596
+ const adapterOf = ({ tableName, credentials, ...clientConfig }) => {
6597
+ const client = new DynamoDBClient({
6598
+ ...clientConfig,
6599
+ credentials: toSdkCredentials(credentials)
6600
+ });
6581
6601
  const store = createDynamoDBStore({
6582
6602
  client,
6583
6603
  tableName
@@ -6612,7 +6632,10 @@ const marked = (target) => ({ [DATABASE_TARGET]: target });
6612
6632
  */
6613
6633
  const dynamoDB = (config) => {
6614
6634
  const { client, adapter } = adapterOf(config);
6615
- const cloudFront = createUpdateRouteInvalidation(config);
6635
+ const cloudFront = createUpdateRouteInvalidation({
6636
+ ...config,
6637
+ credentials: toSdkCredentials(config.credentials)
6638
+ });
6616
6639
  return {
6617
6640
  ...createEngineDatabase({
6618
6641
  name: "dynamoDB",
@@ -8414,10 +8437,11 @@ var SSMKeyPairManager = class {
8414
8437
  //#region iac/templates.ts
8415
8438
  /**
8416
8439
  * The config init writes. With the `resources` init set up, it names them,
8417
- * and an account's access keys are read with `secretEnv`, from the
8440
+ * and an account's access keys are read with `secret()`, from the
8418
8441
  * environment and `.env.hotupdater`, then the config's `secrets` adapter.
8419
- * Without them, as the agent scaffold writes it, it reads every value from
8420
- * the environment. A profile or SSO sign-in is each person's own.
8442
+ * Without them, as the agent scaffold writes it before the agent creates the
8443
+ * resources, it reads their names from the environment, where the agent
8444
+ * records them. A profile or SSO sign-in is each person's own.
8421
8445
  */
8422
8446
  const getConfigScaffold = (build, authMode, resources) => {
8423
8447
  const value = (envKey, resolved) => resolved === void 0 ? `process.env.${envKey}!` : JSON.stringify(resolved);
@@ -8473,31 +8497,19 @@ const awsOptions = {
8473
8497
  };`.trim()
8474
8498
  }];
8475
8499
  break;
8476
- case "account":
8477
- helperStatements = [{
8478
- name: "awsOptions",
8479
- strategy: "merge-object",
8480
- replaceIncompatibleProperties: ["credentials"],
8481
- code: resources === void 0 ? `
8500
+ case "account": helperStatements = [{
8501
+ name: "awsOptions",
8502
+ strategy: "merge-object",
8503
+ replaceIncompatibleProperties: ["credentials"],
8504
+ code: `
8482
8505
  const awsOptions = {
8483
8506
  region: ${region},
8484
8507
  credentials: {
8485
- accessKeyId: process.env.HOT_UPDATER_S3_ACCESS_KEY_ID!,
8486
- secretAccessKey: process.env.HOT_UPDATER_S3_SECRET_ACCESS_KEY!,
8487
- },
8488
- };`.trim() : `
8489
- const awsOptions = {
8490
- region: ${region},
8491
- credentials: async () => {
8492
- const env = await deploySecrets();
8493
- return {
8494
- accessKeyId: env.HOT_UPDATER_S3_ACCESS_KEY_ID,
8495
- secretAccessKey: env.HOT_UPDATER_S3_SECRET_ACCESS_KEY,
8496
- };
8508
+ accessKeyId: secret("HOT_UPDATER_S3_ACCESS_KEY_ID"),
8509
+ secretAccessKey: secret("HOT_UPDATER_S3_SECRET_ACCESS_KEY"),
8497
8510
  },
8498
8511
  };`.trim()
8499
- }];
8500
- if (resources !== void 0) helperStatements.unshift(secretEnvHelper("deploySecrets", ["HOT_UPDATER_S3_ACCESS_KEY_ID", "HOT_UPDATER_S3_SECRET_ACCESS_KEY"]));
8512
+ }];
8501
8513
  }
8502
8514
  const builder = new ConfigBuilder().setBuildType(build).setStorage(storageConfig).setDatabase(databaseConfig).setPlugins({
8503
8515
  imports: [{
@@ -8523,9 +8535,9 @@ const awsOptions = {
8523
8535
  named: [authMode.profile ? "fromIni" : "fromNodeProviderChain"]
8524
8536
  });
8525
8537
  break;
8526
- case "account": if (resources !== void 0) builder.addImport({
8538
+ case "account": builder.addImport({
8527
8539
  pkg: "hot-updater",
8528
- named: ["secretEnv"]
8540
+ named: ["secret"]
8529
8541
  });
8530
8542
  }
8531
8543
  return createHotUpdaterConfigScaffoldFromBuilder(builder, { helperStatements });
@@ -1437,6 +1437,10 @@ const semverSatisfies = (targetAppVersion, currentVersion) => {
1437
1437
  return satisfies(currentCoerce, targetAppVersion);
1438
1438
  };
1439
1439
  //#endregion
1440
+ //#region ../plugin-core/dist/types/index.mjs
1441
+ /** The value of a `Lazy`, calling its function. */
1442
+ const resolveLazy = async (value) => typeof value === "function" ? await value() : value;
1443
+ //#endregion
1440
1444
  //#region ../plugin-core/dist/serverPlugin/definePlugin.mjs
1441
1445
  /** Declares a plugin; Hot Updater's own plugins and third-party ones use the same contract. */
1442
1446
  const definePlugin = (plugin) => plugin;
@@ -4707,7 +4711,7 @@ const createKvAdapter = ({ store, tablePrefix = "" }) => {
4707
4711
  };
4708
4712
  //#endregion
4709
4713
  //#region ../../packages/server/dist/version.mjs
4710
- const HOT_UPDATER_SERVER_VERSION = "1.2.0-rc.7";
4714
+ const HOT_UPDATER_SERVER_VERSION = "1.2.0-rc.8";
4711
4715
  //#endregion
4712
4716
  //#region ../../packages/server/dist/handlerVersionRoutes.mjs
4713
4717
  /**
@@ -14295,10 +14299,30 @@ async apply() {
14295
14299
  };
14296
14300
  };
14297
14301
  //#endregion
14302
+ //#region src/lazyCredentials.ts
14303
+ /**
14304
+ * `credentials` as the AWS SDK takes them: access keys with a lazy field
14305
+ * become a provider, which the SDK calls once, on its first request.
14306
+ */
14307
+ const toSdkCredentials = (credentials) => {
14308
+ if (credentials === void 0 || typeof credentials === "function") return credentials;
14309
+ const { accessKeyId, secretAccessKey, sessionToken, ...rest } = credentials;
14310
+ if (typeof accessKeyId !== "function" && typeof secretAccessKey !== "function" && typeof sessionToken !== "function") return credentials;
14311
+ return async () => ({
14312
+ ...rest,
14313
+ accessKeyId: await resolveLazy(accessKeyId),
14314
+ secretAccessKey: await resolveLazy(secretAccessKey),
14315
+ ...sessionToken === void 0 ? {} : { sessionToken: await resolveLazy(sessionToken) }
14316
+ });
14317
+ };
14318
+ //#endregion
14298
14319
  //#region src/dynamoDB.ts
14299
14320
  /** The DynamoDB client ignores the CloudFront and batching settings. */
14300
- const adapterOf = ({ tableName, ...clientConfig }) => {
14301
- const client = new _aws_sdk_client_dynamodb.DynamoDBClient(clientConfig);
14321
+ const adapterOf = ({ tableName, credentials, ...clientConfig }) => {
14322
+ const client = new _aws_sdk_client_dynamodb.DynamoDBClient({
14323
+ ...clientConfig,
14324
+ credentials: toSdkCredentials(credentials)
14325
+ });
14302
14326
  const store = createDynamoDBStore({
14303
14327
  client,
14304
14328
  tableName
@@ -14323,7 +14347,10 @@ const marked = (target) => ({ [DATABASE_TARGET]: target });
14323
14347
  */
14324
14348
  const dynamoDB = (config) => {
14325
14349
  const { client, adapter } = adapterOf(config);
14326
- const cloudFront = createUpdateRouteInvalidation(config);
14350
+ const cloudFront = createUpdateRouteInvalidation({
14351
+ ...config,
14352
+ credentials: toSdkCredentials(config.credentials)
14353
+ });
14327
14354
  return {
14328
14355
  ...createEngineDatabase({
14329
14356
  name: "dynamoDB",
@@ -14345,8 +14372,11 @@ const dynamoDB = (config) => {
14345
14372
  const PRESIGNED_URL_EXPIRES_IN_SECONDS = 3600;
14346
14373
  const isObjectNotFoundError = (error) => error instanceof Error && (error.name === "NotFound" || error.name === "NoSuchKey");
14347
14374
  function s3Storage(config) {
14348
- const { bucketName, basePath, getDownloadUrl, ...s3Config } = config;
14349
- const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig(s3Config));
14375
+ const { bucketName, basePath, getDownloadUrl, credentials, ...s3Config } = config;
14376
+ const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig({
14377
+ ...s3Config,
14378
+ credentials: toSdkCredentials(credentials)
14379
+ }));
14350
14380
  const normalizedBasePath = basePath?.replace(/^\/+|\/+$/g, "") ?? "";
14351
14381
  const getStorageKey = createStorageKeyBuilder(normalizedBasePath);
14352
14382
  const getListPrefix = (prefix = "") => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/aws",
3
3
  "type": "module",
4
- "version": "1.2.0-rc.7",
4
+ "version": "1.2.0-rc.8",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -45,9 +45,9 @@
45
45
  "es-toolkit": "^1.32.0",
46
46
  "execa": "9.5.2",
47
47
  "mime": "^4.0.4",
48
- "@hot-updater/protocol": "1.2.0-rc.7",
49
- "@hot-updater/mock": "1.2.0-rc.7",
50
- "@hot-updater/test-utils": "1.2.0-rc.7"
48
+ "@hot-updater/protocol": "1.2.0-rc.8",
49
+ "@hot-updater/test-utils": "1.2.0-rc.8",
50
+ "@hot-updater/mock": "1.2.0-rc.8"
51
51
  },
52
52
  "dependencies": {
53
53
  "@aws-sdk/client-cloudfront": "3.1066.0",
@@ -64,9 +64,9 @@
64
64
  "@aws-sdk/lib-dynamodb": "3.1066.0",
65
65
  "@aws-sdk/s3-request-presigner": "3.1066.0",
66
66
  "hono": "4.12.34",
67
- "@hot-updater/cli-tools": "1.2.0-rc.7",
68
- "@hot-updater/plugin-core": "1.2.0-rc.7",
69
- "@hot-updater/server": "1.2.0-rc.7"
67
+ "@hot-updater/cli-tools": "1.2.0-rc.8",
68
+ "@hot-updater/plugin-core": "1.2.0-rc.8",
69
+ "@hot-updater/server": "1.2.0-rc.8"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsdown",