@hot-updater/aws 0.20.14 → 0.21.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
@@ -29,6 +29,8 @@ let __aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
29
29
  __aws_sdk_lib_storage = __toESM(__aws_sdk_lib_storage);
30
30
  let __hot_updater_plugin_core = require("@hot-updater/plugin-core");
31
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);
32
34
  let fs_promises = require("fs/promises");
33
35
  fs_promises = __toESM(fs_promises);
34
36
  let path = require("path");
@@ -1488,11 +1490,13 @@ const s3Storage = (config, hooks) => (_) => {
1488
1490
  const getStorageKey = (0, __hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
1489
1491
  return {
1490
1492
  name: "s3Storage",
1491
- async deleteBundle(bundleId) {
1492
- const Key = getStorageKey(bundleId, "bundle.zip");
1493
+ supportedProtocol: "s3",
1494
+ async delete(storageUri) {
1495
+ const { bucket, key } = (0, __hot_updater_plugin_core.parseStorageUri)(storageUri, "s3");
1496
+ if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
1493
1497
  const listCommand = new __aws_sdk_client_s3.ListObjectsV2Command({
1494
1498
  Bucket: bucketName,
1495
- Prefix: bundleId
1499
+ Prefix: key
1496
1500
  });
1497
1501
  const listResponse = await client.send(listCommand);
1498
1502
  if (listResponse.Contents && listResponse.Contents.length > 0) {
@@ -1504,14 +1508,14 @@ const s3Storage = (config, hooks) => (_) => {
1504
1508
  }
1505
1509
  });
1506
1510
  await client.send(deleteCommand);
1507
- return { storageUri: `s3://${bucketName}/${Key}` };
1511
+ return;
1508
1512
  }
1509
1513
  throw new Error("Bundle Not Found");
1510
1514
  },
1511
- async uploadBundle(bundleId, bundlePath) {
1512
- const Body = await fs_promises.default.readFile(bundlePath);
1513
- const ContentType = src_default.getType(bundlePath) ?? void 0;
1514
- const Key = getStorageKey(bundleId, path.default.basename(bundlePath));
1515
+ async upload(key, filePath) {
1516
+ const Body = await fs_promises.default.readFile(filePath);
1517
+ const ContentType = (0, __hot_updater_plugin_core.getContentType)(filePath);
1518
+ const Key = getStorageKey(key, path.default.basename(filePath));
1515
1519
  const response = await new __aws_sdk_lib_storage.Upload({
1516
1520
  client,
1517
1521
  params: {
@@ -1525,6 +1529,23 @@ const s3Storage = (config, hooks) => (_) => {
1525
1529
  if (!response.Bucket || !response.Key) throw new Error("Upload Failed");
1526
1530
  hooks?.onStorageUploaded?.();
1527
1531
  return { storageUri: `s3://${bucketName}/${Key}` };
1532
+ },
1533
+ async getDownloadUrl(storageUri) {
1534
+ const u = new URL(storageUri);
1535
+ if (u.protocol.replace(":", "") !== "s3") throw new Error("Invalid S3 storage URI protocol");
1536
+ const bucket = u.host;
1537
+ const key = u.pathname.slice(1);
1538
+ if (!bucket || !key) throw new Error("Invalid S3 storage URI: missing bucket or key");
1539
+ try {
1540
+ const signedUrl = await (0, __aws_sdk_s3_request_presigner.getSignedUrl)(client, new __aws_sdk_client_s3.GetObjectCommand({
1541
+ Bucket: bucket,
1542
+ Key: key
1543
+ }), { expiresIn: 3600 });
1544
+ if (!signedUrl) throw new Error("Failed to presign S3 URL");
1545
+ return { fileUrl: signedUrl };
1546
+ } catch (e) {
1547
+ throw new Error(e instanceof Error ? `Failed to presign S3 URL: ${e.message}` : "Failed to presign S3 URL");
1548
+ }
1528
1549
  }
1529
1550
  };
1530
1551
  };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { CloudFrontClient, CreateInvalidationCommand } from "@aws-sdk/client-cloudfront";
2
2
  import { DeleteObjectCommand, DeleteObjectsCommand, GetObjectCommand, ListObjectsV2Command, NoSuchKey, S3Client } from "@aws-sdk/client-s3";
3
3
  import { Upload } from "@aws-sdk/lib-storage";
4
- import { createBlobDatabasePlugin, createStorageKeyBuilder } from "@hot-updater/plugin-core";
4
+ import { createBlobDatabasePlugin, createStorageKeyBuilder, getContentType, parseStorageUri } from "@hot-updater/plugin-core";
5
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
5
6
  import fs from "fs/promises";
6
7
  import path from "path";
7
8
 
@@ -1459,11 +1460,13 @@ const s3Storage = (config, hooks) => (_) => {
1459
1460
  const getStorageKey = createStorageKeyBuilder(config.basePath);
1460
1461
  return {
1461
1462
  name: "s3Storage",
1462
- async deleteBundle(bundleId) {
1463
- const Key = getStorageKey(bundleId, "bundle.zip");
1463
+ supportedProtocol: "s3",
1464
+ async delete(storageUri) {
1465
+ const { bucket, key } = parseStorageUri(storageUri, "s3");
1466
+ if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
1464
1467
  const listCommand = new ListObjectsV2Command({
1465
1468
  Bucket: bucketName,
1466
- Prefix: bundleId
1469
+ Prefix: key
1467
1470
  });
1468
1471
  const listResponse = await client.send(listCommand);
1469
1472
  if (listResponse.Contents && listResponse.Contents.length > 0) {
@@ -1475,14 +1478,14 @@ const s3Storage = (config, hooks) => (_) => {
1475
1478
  }
1476
1479
  });
1477
1480
  await client.send(deleteCommand);
1478
- return { storageUri: `s3://${bucketName}/${Key}` };
1481
+ return;
1479
1482
  }
1480
1483
  throw new Error("Bundle Not Found");
1481
1484
  },
1482
- async uploadBundle(bundleId, bundlePath) {
1483
- const Body = await fs.readFile(bundlePath);
1484
- const ContentType = src_default.getType(bundlePath) ?? void 0;
1485
- const Key = getStorageKey(bundleId, path.basename(bundlePath));
1485
+ async upload(key, filePath) {
1486
+ const Body = await fs.readFile(filePath);
1487
+ const ContentType = getContentType(filePath);
1488
+ const Key = getStorageKey(key, path.basename(filePath));
1486
1489
  const response = await new Upload({
1487
1490
  client,
1488
1491
  params: {
@@ -1496,6 +1499,23 @@ const s3Storage = (config, hooks) => (_) => {
1496
1499
  if (!response.Bucket || !response.Key) throw new Error("Upload Failed");
1497
1500
  hooks?.onStorageUploaded?.();
1498
1501
  return { storageUri: `s3://${bucketName}/${Key}` };
1502
+ },
1503
+ async getDownloadUrl(storageUri) {
1504
+ const u = new URL(storageUri);
1505
+ if (u.protocol.replace(":", "") !== "s3") throw new Error("Invalid S3 storage URI protocol");
1506
+ const bucket = u.host;
1507
+ const key = u.pathname.slice(1);
1508
+ if (!bucket || !key) throw new Error("Invalid S3 storage URI: missing bucket or key");
1509
+ try {
1510
+ const signedUrl = await getSignedUrl(client, new GetObjectCommand({
1511
+ Bucket: bucket,
1512
+ Key: key
1513
+ }), { expiresIn: 3600 });
1514
+ if (!signedUrl) throw new Error("Failed to presign S3 URL");
1515
+ return { fileUrl: signedUrl };
1516
+ } catch (e) {
1517
+ throw new Error(e instanceof Error ? `Failed to presign S3 URL: ${e.message}` : "Failed to presign S3 URL");
1518
+ }
1499
1519
  }
1500
1520
  };
1501
1521
  };
@@ -2913,14 +2913,16 @@ const INIT_BUNDLE_ROLLBACK_UPDATE_INFO = {
2913
2913
  id: NIL_UUID,
2914
2914
  shouldForceUpdate: true,
2915
2915
  status: "ROLLBACK",
2916
- storageUri: null
2916
+ storageUri: null,
2917
+ fileHash: null
2917
2918
  };
2918
2919
  const makeResponse = (bundle, status) => ({
2919
2920
  id: bundle.id,
2920
2921
  message: bundle.message,
2921
2922
  shouldForceUpdate: status === "ROLLBACK" ? true : bundle.shouldForceUpdate,
2922
2923
  status,
2923
- storageUri: bundle.storageUri
2924
+ storageUri: bundle.storageUri,
2925
+ fileHash: bundle.fileHash
2924
2926
  });
2925
2927
  const getUpdateInfo$1 = async (bundles, args) => {
2926
2928
  switch (args._updateStrategy) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/aws",
3
3
  "type": "module",
4
- "version": "0.20.14",
4
+ "version": "0.21.0",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -28,7 +28,8 @@
28
28
  },
29
29
  "./lambda": {
30
30
  "require": "./dist/lambda/index.cjs"
31
- }
31
+ },
32
+ "./package.json": "./package.json"
32
33
  },
33
34
  "files": [
34
35
  "dist",
@@ -45,20 +46,22 @@
45
46
  "mime": "^4.0.4",
46
47
  "picocolors": "1.1.1",
47
48
  "@clack/prompts": "0.10.0",
48
- "@hot-updater/core": "0.20.14",
49
- "@hot-updater/js": "0.20.14"
49
+ "@hot-updater/core": "0.21.0",
50
+ "@hot-updater/js": "0.21.0",
51
+ "@hot-updater/test-utils": "0.21.0"
50
52
  },
51
53
  "dependencies": {
52
54
  "@aws-sdk/client-cloudfront": "3.772.0",
53
55
  "@aws-sdk/client-iam": "3.772.0",
54
56
  "@aws-sdk/client-lambda": "3.772.0",
55
57
  "@aws-sdk/client-s3": "3.772.0",
58
+ "@aws-sdk/s3-request-presigner": "3.772.0",
56
59
  "@aws-sdk/client-ssm": "3.772.0",
57
60
  "@aws-sdk/client-sts": "3.772.0",
58
61
  "@aws-sdk/credential-providers": "3.772.0",
59
62
  "@aws-sdk/lib-storage": "3.772.0",
60
63
  "aws-lambda": "1.0.7",
61
- "@hot-updater/plugin-core": "0.20.14"
64
+ "@hot-updater/plugin-core": "0.21.0"
62
65
  },
63
66
  "scripts": {
64
67
  "build": "tsdown",