@hot-updater/aws 0.28.0 → 0.29.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 CHANGED
@@ -1,4 +1,5 @@
1
- //#region rolldown:runtime
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -19,23 +20,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
19
20
  value: mod,
20
21
  enumerable: true
21
22
  }) : target, mod));
22
-
23
23
  //#endregion
24
- let __aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
25
- __aws_sdk_client_cloudfront = __toESM(__aws_sdk_client_cloudfront);
26
- let __aws_sdk_client_s3 = require("@aws-sdk/client-s3");
27
- __aws_sdk_client_s3 = __toESM(__aws_sdk_client_s3);
28
- let __aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
29
- __aws_sdk_lib_storage = __toESM(__aws_sdk_lib_storage);
30
- let __hot_updater_plugin_core = require("@hot-updater/plugin-core");
31
- __hot_updater_plugin_core = __toESM(__hot_updater_plugin_core);
32
- let __aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
33
- __aws_sdk_s3_request_presigner = __toESM(__aws_sdk_s3_request_presigner);
24
+ let _aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
25
+ let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
26
+ let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
27
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
28
+ let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
34
29
  let fs_promises = require("fs/promises");
35
30
  fs_promises = __toESM(fs_promises);
36
31
  let path = require("path");
37
32
  path = __toESM(path);
38
-
33
+ let _aws_sdk_client_ssm = require("@aws-sdk/client-ssm");
34
+ let _aws_sdk_cloudfront_signer = require("@aws-sdk/cloudfront-signer");
39
35
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/types/other.js
40
36
  const types$1 = {
41
37
  "application/prs.cww": ["cww"],
@@ -849,8 +845,6 @@ const types$1 = {
849
845
  "x-conference/x-cooltalk": ["ice"]
850
846
  };
851
847
  Object.freeze(types$1);
852
- var other_default = types$1;
853
-
854
848
  //#endregion
855
849
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/types/standard.js
856
850
  const types = {
@@ -1296,11 +1290,9 @@ const types = {
1296
1290
  "video/webm": ["webm"]
1297
1291
  };
1298
1292
  Object.freeze(types);
1299
- var standard_default = types;
1300
-
1301
1293
  //#endregion
1302
1294
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/src/Mime.js
1303
- var __classPrivateFieldGet = void 0 && (void 0).__classPrivateFieldGet || function(receiver, state, kind, f) {
1295
+ var __classPrivateFieldGet = function(receiver, state, kind, f) {
1304
1296
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
1305
1297
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
1306
1298
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
@@ -1334,11 +1326,11 @@ var Mime = class {
1334
1326
  }
1335
1327
  return this;
1336
1328
  }
1337
- getType(path$2) {
1338
- if (typeof path$2 !== "string") return null;
1339
- const last = path$2.replace(/^.*[/\\]/, "").toLowerCase();
1329
+ getType(path) {
1330
+ if (typeof path !== "string") return null;
1331
+ const last = path.replace(/^.*[/\\]/, "").toLowerCase();
1340
1332
  const ext = last.replace(/^.*\./, "").toLowerCase();
1341
- const hasPath = last.length < path$2.length;
1333
+ const hasPath = last.length < path.length;
1342
1334
  if (!(ext.length < last.length - 1) && hasPath) return null;
1343
1335
  return __classPrivateFieldGet(this, _Mime_extensionToType, "f").get(ext) ?? null;
1344
1336
  }
@@ -1367,12 +1359,44 @@ var Mime = class {
1367
1359
  }
1368
1360
  };
1369
1361
  _Mime_extensionToType = /* @__PURE__ */ new WeakMap(), _Mime_typeToExtension = /* @__PURE__ */ new WeakMap(), _Mime_typeToExtensions = /* @__PURE__ */ new WeakMap();
1370
- var Mime_default = Mime;
1371
-
1372
1362
  //#endregion
1373
1363
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/src/index.js
1374
- var src_default = new Mime_default(standard_default, other_default)._freeze();
1375
-
1364
+ var src_default = new Mime(types, types$1)._freeze();
1365
+ //#endregion
1366
+ //#region src/runtimeAwsConfig.ts
1367
+ const truthyValues = new Set([
1368
+ "1",
1369
+ "true",
1370
+ "yes",
1371
+ "on"
1372
+ ]);
1373
+ const isTruthy = (value) => {
1374
+ if (!value) return false;
1375
+ return truthyValues.has(value.toLowerCase());
1376
+ };
1377
+ const getAwsEndpointUrl = () => {
1378
+ return process.env.AWS_ENDPOINT_URL?.trim() || void 0;
1379
+ };
1380
+ const shouldForcePathStyle = (forcePathStyle, endpoint) => {
1381
+ if (forcePathStyle !== void 0) return forcePathStyle;
1382
+ if (isTruthy(process.env.AWS_S3_FORCE_PATH_STYLE)) return true;
1383
+ return endpoint !== void 0;
1384
+ };
1385
+ const applyS3RuntimeAwsConfig = (config) => {
1386
+ const endpoint = config.endpoint ?? getAwsEndpointUrl();
1387
+ return {
1388
+ ...config,
1389
+ endpoint,
1390
+ forcePathStyle: shouldForcePathStyle(config.forcePathStyle, endpoint)
1391
+ };
1392
+ };
1393
+ const applySsmRuntimeAwsConfig = (config) => {
1394
+ const endpoint = config.endpoint ?? getAwsEndpointUrl();
1395
+ return {
1396
+ ...config,
1397
+ endpoint
1398
+ };
1399
+ };
1376
1400
  //#endregion
1377
1401
  //#region src/utils/streamToString.ts
1378
1402
  const streamToString = (stream) => {
@@ -1383,16 +1407,18 @@ const streamToString = (stream) => {
1383
1407
  stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
1384
1408
  });
1385
1409
  };
1386
-
1387
1410
  //#endregion
1388
1411
  //#region src/s3Database.ts
1412
+ const DEFAULT_INVALIDATION_POLL_INTERVAL_MS = 2e3;
1413
+ const DEFAULT_INVALIDATION_TIMEOUT_MS = 300 * 1e3;
1414
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1389
1415
  /**
1390
1416
  * Loads JSON data from S3.
1391
1417
  * Returns null if NoSuchKey error occurs.
1392
1418
  */
1393
1419
  async function loadJsonFromS3(client, bucket, key) {
1394
1420
  try {
1395
- const { Body } = await client.send(new __aws_sdk_client_s3.GetObjectCommand({
1421
+ const { Body } = await client.send(new _aws_sdk_client_s3.GetObjectCommand({
1396
1422
  Bucket: bucket,
1397
1423
  Key: key
1398
1424
  }));
@@ -1400,7 +1426,7 @@ async function loadJsonFromS3(client, bucket, key) {
1400
1426
  const bodyContents = await streamToString(Body);
1401
1427
  return JSON.parse(bodyContents);
1402
1428
  } catch (e) {
1403
- if (e instanceof __aws_sdk_client_s3.NoSuchKey) return null;
1429
+ if (e instanceof _aws_sdk_client_s3.NoSuchKey) return null;
1404
1430
  throw e;
1405
1431
  }
1406
1432
  }
@@ -1408,7 +1434,7 @@ async function loadJsonFromS3(client, bucket, key) {
1408
1434
  * Converts data to JSON string and uploads to S3.
1409
1435
  */
1410
1436
  async function uploadJsonToS3(client, bucket, key, data) {
1411
- await new __aws_sdk_lib_storage.Upload({
1437
+ await new _aws_sdk_lib_storage.Upload({
1412
1438
  client,
1413
1439
  params: {
1414
1440
  Bucket: bucket,
@@ -1423,7 +1449,7 @@ async function listObjectsInS3(client, bucketName, prefix) {
1423
1449
  let continuationToken;
1424
1450
  const keys = [];
1425
1451
  do {
1426
- const response = await client.send(new __aws_sdk_client_s3.ListObjectsV2Command({
1452
+ const response = await client.send(new _aws_sdk_client_s3.ListObjectsV2Command({
1427
1453
  Bucket: bucketName,
1428
1454
  Prefix: prefix,
1429
1455
  ContinuationToken: continuationToken
@@ -1435,7 +1461,7 @@ async function listObjectsInS3(client, bucketName, prefix) {
1435
1461
  return keys;
1436
1462
  }
1437
1463
  async function deleteObjectInS3(client, bucketName, key) {
1438
- await client.send(new __aws_sdk_client_s3.DeleteObjectCommand({
1464
+ await client.send(new _aws_sdk_client_s3.DeleteObjectCommand({
1439
1465
  Bucket: bucketName,
1440
1466
  Key: key
1441
1467
  }));
@@ -1443,26 +1469,50 @@ async function deleteObjectInS3(client, bucketName, key) {
1443
1469
  /**
1444
1470
  * Invalidates CloudFront cache for the given paths.
1445
1471
  */
1446
- async function invalidateCloudFront(client, distributionId, paths) {
1472
+ async function invalidateCloudFront(client, distributionId, paths, options) {
1447
1473
  if (paths.length === 0) return;
1448
1474
  const timestamp = Date.now();
1449
- await client.send(new __aws_sdk_client_cloudfront.CreateInvalidationCommand({
1450
- DistributionId: distributionId,
1451
- InvalidationBatch: {
1452
- CallerReference: `invalidation-${timestamp}`,
1453
- Paths: {
1454
- Quantity: paths.length,
1455
- Items: paths
1475
+ try {
1476
+ const response = await client.send(new _aws_sdk_client_cloudfront.CreateInvalidationCommand({
1477
+ DistributionId: distributionId,
1478
+ InvalidationBatch: {
1479
+ CallerReference: `invalidation-${timestamp}`,
1480
+ Paths: {
1481
+ Quantity: paths.length,
1482
+ Items: paths
1483
+ }
1456
1484
  }
1485
+ }));
1486
+ if (!options?.shouldWaitForInvalidation) return;
1487
+ const invalidationId = response.Invalidation?.Id;
1488
+ if (!invalidationId) throw new Error("CloudFront invalidation response is missing Invalidation.Id");
1489
+ if (response.Invalidation?.Status === "Completed") return;
1490
+ const timeoutMs = DEFAULT_INVALIDATION_TIMEOUT_MS;
1491
+ const pollIntervalMs = DEFAULT_INVALIDATION_POLL_INTERVAL_MS;
1492
+ const deadline = Date.now() + timeoutMs;
1493
+ while (Date.now() < deadline) {
1494
+ await sleep(pollIntervalMs);
1495
+ if ((await client.send(new _aws_sdk_client_cloudfront.GetInvalidationCommand({
1496
+ DistributionId: distributionId,
1497
+ Id: invalidationId
1498
+ }))).Invalidation?.Status === "Completed") return;
1457
1499
  }
1458
- }));
1500
+ throw new Error(`Timed out waiting for CloudFront invalidation ${invalidationId} to complete after ${timeoutMs}ms`);
1501
+ } catch (error) {
1502
+ if (options?.shouldWaitForInvalidation) throw error;
1503
+ const message = error instanceof Error ? error.message : "Unknown invalidation error";
1504
+ console.warn(`[hot-updater/aws] CloudFront invalidation failed for distribution ${distributionId}; continuing without cache invalidation.`, {
1505
+ error: message,
1506
+ paths
1507
+ });
1508
+ }
1459
1509
  }
1460
- const s3Database = (0, __hot_updater_plugin_core.createBlobDatabasePlugin)({
1510
+ const s3Database = (0, _hot_updater_plugin_core.createBlobDatabasePlugin)({
1461
1511
  name: "s3Database",
1462
1512
  factory: (config) => {
1463
- const { bucketName, cloudfrontDistributionId, apiBasePath = "/api/check-update",...s3Config } = config;
1464
- const client = new __aws_sdk_client_s3.S3Client(s3Config);
1465
- const cloudfrontClient = cloudfrontDistributionId ? new __aws_sdk_client_cloudfront.CloudFrontClient({
1513
+ const { bucketName, cloudfrontDistributionId, apiBasePath = "/api/check-update", shouldWaitForInvalidation = false, ...s3Config } = config;
1514
+ const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig(s3Config));
1515
+ const cloudfrontClient = cloudfrontDistributionId ? new _aws_sdk_client_cloudfront.CloudFrontClient({
1466
1516
  credentials: s3Config.credentials,
1467
1517
  region: s3Config.region
1468
1518
  }) : void 0;
@@ -1473,33 +1523,32 @@ const s3Database = (0, __hot_updater_plugin_core.createBlobDatabasePlugin)({
1473
1523
  uploadObject: (key, data) => uploadJsonToS3(client, bucketName, key, data),
1474
1524
  deleteObject: (key) => deleteObjectInS3(client, bucketName, key),
1475
1525
  invalidatePaths: (pathsToInvalidate) => {
1476
- if (cloudfrontClient && cloudfrontDistributionId && pathsToInvalidate.length > 0) return invalidateCloudFront(cloudfrontClient, cloudfrontDistributionId, pathsToInvalidate);
1526
+ if (cloudfrontClient && cloudfrontDistributionId && pathsToInvalidate.length > 0) return invalidateCloudFront(cloudfrontClient, cloudfrontDistributionId, pathsToInvalidate, { shouldWaitForInvalidation });
1477
1527
  return Promise.resolve();
1478
1528
  }
1479
1529
  };
1480
1530
  }
1481
1531
  });
1482
-
1483
1532
  //#endregion
1484
1533
  //#region src/s3Storage.ts
1485
- const s3Storage = (0, __hot_updater_plugin_core.createStoragePlugin)({
1534
+ const s3Storage = (0, _hot_updater_plugin_core.createStoragePlugin)({
1486
1535
  name: "s3Storage",
1487
1536
  supportedProtocol: "s3",
1488
1537
  factory: (config) => {
1489
- const { bucketName,...s3Config } = config;
1490
- const client = new __aws_sdk_client_s3.S3Client(s3Config);
1491
- const getStorageKey = (0, __hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
1538
+ const { bucketName, ...s3Config } = config;
1539
+ const client = new _aws_sdk_client_s3.S3Client(applyS3RuntimeAwsConfig(s3Config));
1540
+ const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
1492
1541
  return {
1493
1542
  async delete(storageUri) {
1494
- const { bucket, key } = (0, __hot_updater_plugin_core.parseStorageUri)(storageUri, "s3");
1543
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "s3");
1495
1544
  if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
1496
- const listCommand = new __aws_sdk_client_s3.ListObjectsV2Command({
1545
+ const listCommand = new _aws_sdk_client_s3.ListObjectsV2Command({
1497
1546
  Bucket: bucketName,
1498
1547
  Prefix: key
1499
1548
  });
1500
1549
  const listResponse = await client.send(listCommand);
1501
1550
  if (listResponse.Contents && listResponse.Contents.length > 0) {
1502
- const deleteCommand = new __aws_sdk_client_s3.DeleteObjectsCommand({
1551
+ const deleteCommand = new _aws_sdk_client_s3.DeleteObjectsCommand({
1503
1552
  Bucket: bucketName,
1504
1553
  Delete: {
1505
1554
  Objects: listResponse.Contents.map((obj) => ({ Key: obj.Key })),
@@ -1513,9 +1562,9 @@ const s3Storage = (0, __hot_updater_plugin_core.createStoragePlugin)({
1513
1562
  },
1514
1563
  async upload(key, filePath) {
1515
1564
  const Body = await fs_promises.default.readFile(filePath);
1516
- const ContentType = (0, __hot_updater_plugin_core.getContentType)(filePath);
1565
+ const ContentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
1517
1566
  const Key = getStorageKey(key, path.default.basename(filePath));
1518
- const response = await new __aws_sdk_lib_storage.Upload({
1567
+ const response = await new _aws_sdk_lib_storage.Upload({
1519
1568
  client,
1520
1569
  params: {
1521
1570
  ContentType,
@@ -1535,7 +1584,7 @@ const s3Storage = (0, __hot_updater_plugin_core.createStoragePlugin)({
1535
1584
  const key = u.pathname.slice(1);
1536
1585
  if (!bucket || !key) throw new Error("Invalid S3 storage URI: missing bucket or key");
1537
1586
  try {
1538
- const signedUrl = await (0, __aws_sdk_s3_request_presigner.getSignedUrl)(client, new __aws_sdk_client_s3.GetObjectCommand({
1587
+ const signedUrl = await (0, _aws_sdk_s3_request_presigner.getSignedUrl)(client, new _aws_sdk_client_s3.GetObjectCommand({
1539
1588
  Bucket: bucket,
1540
1589
  Key: key
1541
1590
  }), { expiresIn: 3600 });
@@ -1548,7 +1597,78 @@ const s3Storage = (0, __hot_updater_plugin_core.createStoragePlugin)({
1548
1597
  };
1549
1598
  }
1550
1599
  });
1551
-
1552
1600
  //#endregion
1601
+ //#region src/withCloudFrontSignedUrl.ts
1602
+ const ONE_YEAR_IN_SECONDS = 3600 * 24 * 365;
1603
+ const privateKeyCache = /* @__PURE__ */ new Map();
1604
+ const getPrivateKeyFromSsm = async (region, parameterName) => {
1605
+ if (!region) throw new Error(`Invalid AWS region format: ${region}. Expected format like 'us-east-1' or 'ap-southeast-1'`);
1606
+ const parameter = (await new _aws_sdk_client_ssm.SSM(applySsmRuntimeAwsConfig({ region })).getParameter({
1607
+ Name: parameterName,
1608
+ WithDecryption: true
1609
+ })).Parameter;
1610
+ if (!parameter) throw new Error(`Failed to retrieve private key from SSM parameter: ${parameterName}`);
1611
+ const parameterValue = parameter.Value;
1612
+ if (!parameterValue) throw new Error(`Failed to retrieve private key from SSM parameter: ${parameterName}`);
1613
+ let keyPair;
1614
+ try {
1615
+ keyPair = JSON.parse(parameterValue);
1616
+ } catch (error) {
1617
+ throw new Error(`Invalid JSON format in SSM parameter: ${parameterName}. ${error instanceof Error ? error.message : String(error)}`);
1618
+ }
1619
+ const privateKey = keyPair.privateKey;
1620
+ if (!privateKey || typeof privateKey !== "string") throw new Error(`Invalid private key format in SSM parameter: ${parameterName}`);
1621
+ return privateKey;
1622
+ };
1623
+ const resolvePrivateKey = (config) => {
1624
+ if ("getPrivateKey" in config && typeof config.getPrivateKey === "function") return config.getPrivateKey();
1625
+ const cacheKey = `${config.ssmRegion}:${config.ssmParameterName}`;
1626
+ const cachedPrivateKey = privateKeyCache.get(cacheKey);
1627
+ if (cachedPrivateKey) return cachedPrivateKey;
1628
+ const privateKeyPromise = getPrivateKeyFromSsm(config.ssmRegion, config.ssmParameterName).catch((error) => {
1629
+ privateKeyCache.delete(cacheKey);
1630
+ throw error;
1631
+ });
1632
+ privateKeyCache.set(cacheKey, privateKeyPromise);
1633
+ return privateKeyPromise;
1634
+ };
1635
+ const resolvePublicBaseUrl = async (config, context) => {
1636
+ const publicBaseUrl = typeof config.publicBaseUrl === "function" ? await config.publicBaseUrl(context) : config.publicBaseUrl;
1637
+ if (!publicBaseUrl) throw new Error("CloudFront publicBaseUrl resolver returned an empty URL");
1638
+ return publicBaseUrl;
1639
+ };
1640
+ const withCloudFrontSignedUrl = (storageFactory, config) => {
1641
+ return () => {
1642
+ const baseStorage = storageFactory();
1643
+ return {
1644
+ ...baseStorage,
1645
+ name: `${baseStorage.name}WithCloudFrontSignedUrl`,
1646
+ async getDownloadUrl(storageUri, context) {
1647
+ const storageUrl = new URL(storageUri);
1648
+ if (storageUrl.protocol !== "s3:") return baseStorage.getDownloadUrl(storageUri, context);
1649
+ const [privateKey, publicBaseUrl] = await Promise.all([resolvePrivateKey(config), resolvePublicBaseUrl(config, context)]);
1650
+ const url = new URL(publicBaseUrl);
1651
+ url.pathname = storageUrl.pathname;
1652
+ url.search = "";
1653
+ return { fileUrl: (0, _aws_sdk_cloudfront_signer.getSignedUrl)({
1654
+ url: url.toString(),
1655
+ keyPairId: config.keyPairId,
1656
+ privateKey,
1657
+ dateLessThan: new Date(Date.now() + (config.expiresSeconds ?? ONE_YEAR_IN_SECONDS) * 1e3).toISOString()
1658
+ }) };
1659
+ }
1660
+ };
1661
+ };
1662
+ };
1663
+ //#endregion
1664
+ //#region src/s3LambdaEdgeStorage.ts
1665
+ const awsLambdaEdgeStorage = (config, hooks) => {
1666
+ return withCloudFrontSignedUrl(s3Storage(config, hooks), config);
1667
+ };
1668
+ const s3LambdaEdgeStorage = awsLambdaEdgeStorage;
1669
+ //#endregion
1670
+ exports.awsLambdaEdgeStorage = awsLambdaEdgeStorage;
1553
1671
  exports.s3Database = s3Database;
1554
- exports.s3Storage = s3Storage;
1672
+ exports.s3LambdaEdgeStorage = s3LambdaEdgeStorage;
1673
+ exports.s3Storage = s3Storage;
1674
+ exports.withCloudFrontSignedUrl = withCloudFrontSignedUrl;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import * as _hot_updater_plugin_core1 from "@hot-updater/plugin-core";
1
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
2
+ import { StoragePlugin, StoragePluginHooks, StorageResolveContext } from "@hot-updater/plugin-core";
2
3
  import { S3ClientConfig } from "@aws-sdk/client-s3";
3
4
 
4
5
  //#region src/s3Database.d.ts
@@ -12,9 +13,16 @@ interface S3DatabaseConfig extends S3ClientConfig {
12
13
  * where CloudFront is not available.
13
14
  */
14
15
  cloudfrontDistributionId?: string;
16
+ /**
17
+ * Wait for CloudFront invalidations to reach `Completed` before finishing.
18
+ *
19
+ * When enabled, invalidation failures and timeouts are surfaced to callers
20
+ * instead of being logged and ignored.
21
+ */
22
+ shouldWaitForInvalidation?: boolean;
15
23
  apiBasePath?: string;
16
24
  }
17
- declare const s3Database: (config: S3DatabaseConfig, hooks?: _hot_updater_plugin_core1.DatabasePluginHooks) => () => _hot_updater_plugin_core1.DatabasePlugin;
25
+ declare const s3Database: (config: S3DatabaseConfig, hooks?: _$_hot_updater_plugin_core0.DatabasePluginHooks) => () => _$_hot_updater_plugin_core0.DatabasePlugin<unknown>;
18
26
  //#endregion
19
27
  //#region src/s3Storage.d.ts
20
28
  interface S3StorageConfig extends S3ClientConfig {
@@ -24,6 +32,31 @@ interface S3StorageConfig extends S3ClientConfig {
24
32
  */
25
33
  basePath?: string;
26
34
  }
27
- declare const s3Storage: (config: S3StorageConfig, hooks?: _hot_updater_plugin_core1.StoragePluginHooks) => () => _hot_updater_plugin_core1.StoragePlugin;
35
+ declare const s3Storage: (config: S3StorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
36
+ //#endregion
37
+ //#region src/withCloudFrontSignedUrl.d.ts
38
+ interface CloudFrontPrivateKeyFromGetter {
39
+ getPrivateKey: () => Promise<string>;
40
+ ssmParameterName?: never;
41
+ ssmRegion?: never;
42
+ }
43
+ interface CloudFrontPrivateKeyFromSsm {
44
+ getPrivateKey?: never;
45
+ ssmParameterName: string;
46
+ ssmRegion: string;
47
+ }
48
+ type PublicBaseUrlResolver<TContext = unknown> = (context?: StorageResolveContext<TContext>) => string | Promise<string>;
49
+ type CloudFrontSignedUrlConfig = CloudFrontPrivateKeyFromGetter | CloudFrontPrivateKeyFromSsm;
50
+ type WithCloudFrontSignedUrlOptions<TContext = unknown> = CloudFrontSignedUrlConfig & {
51
+ keyPairId: string;
52
+ publicBaseUrl: string | PublicBaseUrlResolver<TContext>;
53
+ expiresSeconds?: number;
54
+ };
55
+ declare const withCloudFrontSignedUrl: <TContext = unknown>(storageFactory: () => StoragePlugin<TContext>, config: WithCloudFrontSignedUrlOptions<TContext>) => () => StoragePlugin<TContext>;
56
+ //#endregion
57
+ //#region src/s3LambdaEdgeStorage.d.ts
58
+ type AwsLambdaEdgeStorageConfig = S3StorageConfig & WithCloudFrontSignedUrlOptions;
59
+ declare const awsLambdaEdgeStorage: (config: AwsLambdaEdgeStorageConfig, hooks?: StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
60
+ declare const s3LambdaEdgeStorage: (config: AwsLambdaEdgeStorageConfig, hooks?: StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
28
61
  //#endregion
29
- export { S3DatabaseConfig, S3StorageConfig, s3Database, s3Storage };
62
+ export { AwsLambdaEdgeStorageConfig, CloudFrontSignedUrlConfig, PublicBaseUrlResolver, S3DatabaseConfig, S3StorageConfig, WithCloudFrontSignedUrlOptions, awsLambdaEdgeStorage, s3Database, s3LambdaEdgeStorage, s3Storage, withCloudFrontSignedUrl };
@@ -0,0 +1,62 @@
1
+ import { S3ClientConfig } from "@aws-sdk/client-s3";
2
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
3
+ import { StoragePlugin, StoragePluginHooks, StorageResolveContext } from "@hot-updater/plugin-core";
4
+
5
+ //#region src/s3Database.d.ts
6
+ interface S3DatabaseConfig extends S3ClientConfig {
7
+ bucketName: string;
8
+ /**
9
+ * CloudFront distribution ID used for cache invalidation.
10
+ *
11
+ * If omitted or an empty string, CloudFront invalidation is skipped.
12
+ * This is useful for local development environments (e.g. Localstack)
13
+ * where CloudFront is not available.
14
+ */
15
+ cloudfrontDistributionId?: string;
16
+ /**
17
+ * Wait for CloudFront invalidations to reach `Completed` before finishing.
18
+ *
19
+ * When enabled, invalidation failures and timeouts are surfaced to callers
20
+ * instead of being logged and ignored.
21
+ */
22
+ shouldWaitForInvalidation?: boolean;
23
+ apiBasePath?: string;
24
+ }
25
+ declare const s3Database: (config: S3DatabaseConfig, hooks?: _$_hot_updater_plugin_core0.DatabasePluginHooks) => () => _$_hot_updater_plugin_core0.DatabasePlugin<unknown>;
26
+ //#endregion
27
+ //#region src/s3Storage.d.ts
28
+ interface S3StorageConfig extends S3ClientConfig {
29
+ bucketName: string;
30
+ /**
31
+ * Base path where bundles will be stored in the bucket
32
+ */
33
+ basePath?: string;
34
+ }
35
+ declare const s3Storage: (config: S3StorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
36
+ //#endregion
37
+ //#region src/withCloudFrontSignedUrl.d.ts
38
+ interface CloudFrontPrivateKeyFromGetter {
39
+ getPrivateKey: () => Promise<string>;
40
+ ssmParameterName?: never;
41
+ ssmRegion?: never;
42
+ }
43
+ interface CloudFrontPrivateKeyFromSsm {
44
+ getPrivateKey?: never;
45
+ ssmParameterName: string;
46
+ ssmRegion: string;
47
+ }
48
+ type PublicBaseUrlResolver<TContext = unknown> = (context?: StorageResolveContext<TContext>) => string | Promise<string>;
49
+ type CloudFrontSignedUrlConfig = CloudFrontPrivateKeyFromGetter | CloudFrontPrivateKeyFromSsm;
50
+ type WithCloudFrontSignedUrlOptions<TContext = unknown> = CloudFrontSignedUrlConfig & {
51
+ keyPairId: string;
52
+ publicBaseUrl: string | PublicBaseUrlResolver<TContext>;
53
+ expiresSeconds?: number;
54
+ };
55
+ declare const withCloudFrontSignedUrl: <TContext = unknown>(storageFactory: () => StoragePlugin<TContext>, config: WithCloudFrontSignedUrlOptions<TContext>) => () => StoragePlugin<TContext>;
56
+ //#endregion
57
+ //#region src/s3LambdaEdgeStorage.d.ts
58
+ type AwsLambdaEdgeStorageConfig = S3StorageConfig & WithCloudFrontSignedUrlOptions;
59
+ declare const awsLambdaEdgeStorage: (config: AwsLambdaEdgeStorageConfig, hooks?: StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
60
+ declare const s3LambdaEdgeStorage: (config: AwsLambdaEdgeStorageConfig, hooks?: StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
61
+ //#endregion
62
+ export { AwsLambdaEdgeStorageConfig, CloudFrontSignedUrlConfig, PublicBaseUrlResolver, S3DatabaseConfig, S3StorageConfig, WithCloudFrontSignedUrlOptions, awsLambdaEdgeStorage, s3Database, s3LambdaEdgeStorage, s3Storage, withCloudFrontSignedUrl };