@hot-updater/aws 0.32.0 → 0.33.1
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/iac/index.cjs +181 -15
- package/dist/iac/index.mjs +181 -15
- package/dist/index.cjs +189 -44
- package/dist/index.d.cts +6 -2
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +190 -45
- package/dist/lambda/index.cjs +1481 -2525
- package/package.json +22 -19
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { CloudFrontClient, CreateInvalidationCommand, GetInvalidationCommand } from "@aws-sdk/client-cloudfront";
|
|
2
|
-
import { DeleteObjectCommand, DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, NoSuchKey, S3Client } from "@aws-sdk/client-s3";
|
|
3
|
-
import { Upload } from "@aws-sdk/lib-storage";
|
|
2
|
+
import { DeleteObjectCommand, DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, NoSuchKey, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
4
3
|
import { createBlobDatabasePlugin, createStorageKeyBuilder, createUniversalStoragePlugin, getContentType, parseStorageUri } from "@hot-updater/plugin-core";
|
|
5
4
|
import fs from "fs/promises";
|
|
6
5
|
import path from "path";
|
|
6
|
+
import { Upload } from "@aws-sdk/lib-storage";
|
|
7
7
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
8
8
|
import { SSM } from "@aws-sdk/client-ssm";
|
|
9
9
|
import { getSignedUrl as getSignedUrl$1 } from "@aws-sdk/cloudfront-signer";
|
|
10
|
-
//#region ../../node_modules/.pnpm/mime@4.0
|
|
10
|
+
//#region ../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/types/other.js
|
|
11
11
|
const types$1 = {
|
|
12
12
|
"application/prs.cww": ["cww"],
|
|
13
13
|
"application/prs.xsf+xml": ["xsf"],
|
|
@@ -46,6 +46,7 @@ const types$1 = {
|
|
|
46
46
|
"application/vnd.aristanetworks.swi": ["swi"],
|
|
47
47
|
"application/vnd.astraea-software.iota": ["iota"],
|
|
48
48
|
"application/vnd.audiograph": ["aep"],
|
|
49
|
+
"application/vnd.autodesk.fbx": ["fbx"],
|
|
49
50
|
"application/vnd.balsamiq.bmml+xml": ["bmml"],
|
|
50
51
|
"application/vnd.blueice.multipass": ["mpm"],
|
|
51
52
|
"application/vnd.bmi": ["bmi"],
|
|
@@ -81,6 +82,7 @@ const types$1 = {
|
|
|
81
82
|
"application/vnd.dart": ["dart"],
|
|
82
83
|
"application/vnd.data-vision.rdz": ["rdz"],
|
|
83
84
|
"application/vnd.dbf": ["dbf"],
|
|
85
|
+
"application/vnd.dcmp+xml": ["dcmp"],
|
|
84
86
|
"application/vnd.dece.data": [
|
|
85
87
|
"uvf",
|
|
86
88
|
"uvvf",
|
|
@@ -134,6 +136,7 @@ const types$1 = {
|
|
|
134
136
|
"application/vnd.fuzzysheet": ["fzs"],
|
|
135
137
|
"application/vnd.genomatix.tuxedo": ["txd"],
|
|
136
138
|
"application/vnd.geogebra.file": ["ggb"],
|
|
139
|
+
"application/vnd.geogebra.slides": ["ggs"],
|
|
137
140
|
"application/vnd.geogebra.tool": ["ggt"],
|
|
138
141
|
"application/vnd.geometry-explorer": ["gex", "gre"],
|
|
139
142
|
"application/vnd.geonext": ["gxt"],
|
|
@@ -141,10 +144,17 @@ const types$1 = {
|
|
|
141
144
|
"application/vnd.geospace": ["g3w"],
|
|
142
145
|
"application/vnd.gmx": ["gmx"],
|
|
143
146
|
"application/vnd.google-apps.document": ["gdoc"],
|
|
147
|
+
"application/vnd.google-apps.drawing": ["gdraw"],
|
|
148
|
+
"application/vnd.google-apps.form": ["gform"],
|
|
149
|
+
"application/vnd.google-apps.jam": ["gjam"],
|
|
150
|
+
"application/vnd.google-apps.map": ["gmap"],
|
|
144
151
|
"application/vnd.google-apps.presentation": ["gslides"],
|
|
152
|
+
"application/vnd.google-apps.script": ["gscript"],
|
|
153
|
+
"application/vnd.google-apps.site": ["gsite"],
|
|
145
154
|
"application/vnd.google-apps.spreadsheet": ["gsheet"],
|
|
146
155
|
"application/vnd.google-earth.kml+xml": ["kml"],
|
|
147
156
|
"application/vnd.google-earth.kmz": ["kmz"],
|
|
157
|
+
"application/vnd.gov.sk.xmldatacontainer+xml": ["xdcf"],
|
|
148
158
|
"application/vnd.grafeq": ["gqf", "gqs"],
|
|
149
159
|
"application/vnd.groove-account": ["gac"],
|
|
150
160
|
"application/vnd.groove-help": ["ghf"],
|
|
@@ -271,6 +281,7 @@ const types$1 = {
|
|
|
271
281
|
"application/vnd.ms-powerpoint.slideshow.macroenabled.12": ["ppsm"],
|
|
272
282
|
"application/vnd.ms-powerpoint.template.macroenabled.12": ["potm"],
|
|
273
283
|
"application/vnd.ms-project": ["*mpp", "mpt"],
|
|
284
|
+
"application/vnd.ms-visio.viewer": ["vdx"],
|
|
274
285
|
"application/vnd.ms-word.document.macroenabled.12": ["docm"],
|
|
275
286
|
"application/vnd.ms-word.template.macroenabled.12": ["dotm"],
|
|
276
287
|
"application/vnd.ms-works": [
|
|
@@ -285,6 +296,7 @@ const types$1 = {
|
|
|
285
296
|
"application/vnd.musician": ["mus"],
|
|
286
297
|
"application/vnd.muvee.style": ["msty"],
|
|
287
298
|
"application/vnd.mynfc": ["taglet"],
|
|
299
|
+
"application/vnd.nato.bindingdataobject+xml": ["bdo"],
|
|
288
300
|
"application/vnd.neurolanguage.nlu": ["nlu"],
|
|
289
301
|
"application/vnd.nitf": ["ntf", "nitf"],
|
|
290
302
|
"application/vnd.noblenet-directory": ["nnd"],
|
|
@@ -344,6 +356,9 @@ const types$1 = {
|
|
|
344
356
|
"application/vnd.pocketlearn": ["plf"],
|
|
345
357
|
"application/vnd.powerbuilder6": ["pbd"],
|
|
346
358
|
"application/vnd.previewsystems.box": ["box"],
|
|
359
|
+
"application/vnd.procrate.brushset": ["brushset"],
|
|
360
|
+
"application/vnd.procreate.brush": ["brush"],
|
|
361
|
+
"application/vnd.procreate.dream": ["drm"],
|
|
347
362
|
"application/vnd.proteus.magazine": ["mgz"],
|
|
348
363
|
"application/vnd.publishare-delta-tree": ["qps"],
|
|
349
364
|
"application/vnd.pvi.ptid1": ["ptid"],
|
|
@@ -427,7 +442,9 @@ const types$1 = {
|
|
|
427
442
|
"vsd",
|
|
428
443
|
"vst",
|
|
429
444
|
"vss",
|
|
430
|
-
"vsw"
|
|
445
|
+
"vsw",
|
|
446
|
+
"vsdx",
|
|
447
|
+
"vtx"
|
|
431
448
|
],
|
|
432
449
|
"application/vnd.visionary": ["vis"],
|
|
433
450
|
"application/vnd.vsf": ["vsf"],
|
|
@@ -467,6 +484,7 @@ const types$1 = {
|
|
|
467
484
|
"application/x-bcpio": ["bcpio"],
|
|
468
485
|
"application/x-bdoc": ["*bdoc"],
|
|
469
486
|
"application/x-bittorrent": ["torrent"],
|
|
487
|
+
"application/x-blender": ["blend"],
|
|
470
488
|
"application/x-blorb": ["blb", "blorb"],
|
|
471
489
|
"application/x-bzip": ["bz"],
|
|
472
490
|
"application/x-bzip2": ["bz2", "boz"],
|
|
@@ -483,6 +501,7 @@ const types$1 = {
|
|
|
483
501
|
"application/x-chess-pgn": ["pgn"],
|
|
484
502
|
"application/x-chrome-extension": ["crx"],
|
|
485
503
|
"application/x-cocoa": ["cco"],
|
|
504
|
+
"application/x-compressed": ["*rar"],
|
|
486
505
|
"application/x-conference": ["nsc"],
|
|
487
506
|
"application/x-cpio": ["cpio"],
|
|
488
507
|
"application/x-csh": ["csh"],
|
|
@@ -527,6 +546,7 @@ const types$1 = {
|
|
|
527
546
|
"application/x-hdf": ["hdf"],
|
|
528
547
|
"application/x-httpd-php": ["php"],
|
|
529
548
|
"application/x-install-instructions": ["install"],
|
|
549
|
+
"application/x-ipynb+json": ["ipynb"],
|
|
530
550
|
"application/x-iso9660-image": ["*iso"],
|
|
531
551
|
"application/x-iwork-keynote-sffkey": ["*key"],
|
|
532
552
|
"application/x-iwork-numbers-sffnumbers": ["*numbers"],
|
|
@@ -623,6 +643,7 @@ const types$1 = {
|
|
|
623
643
|
"application/x-xliff+xml": ["*xlf"],
|
|
624
644
|
"application/x-xpinstall": ["xpi"],
|
|
625
645
|
"application/x-xz": ["xz"],
|
|
646
|
+
"application/x-zip-compressed": ["*zip"],
|
|
626
647
|
"application/x-zmachine": [
|
|
627
648
|
"z1",
|
|
628
649
|
"z2",
|
|
@@ -671,6 +692,7 @@ const types$1 = {
|
|
|
671
692
|
"image/prs.pti": ["pti"],
|
|
672
693
|
"image/vnd.adobe.photoshop": ["psd"],
|
|
673
694
|
"image/vnd.airzip.accelerator.azv": ["azv"],
|
|
695
|
+
"image/vnd.blockfact.facti": ["facti"],
|
|
674
696
|
"image/vnd.dece.graphic": [
|
|
675
697
|
"uvi",
|
|
676
698
|
"uvvi",
|
|
@@ -698,6 +720,7 @@ const types$1 = {
|
|
|
698
720
|
"image/vnd.xiff": ["xif"],
|
|
699
721
|
"image/vnd.zbrush.pcx": ["pcx"],
|
|
700
722
|
"image/x-3ds": ["3ds"],
|
|
723
|
+
"image/x-adobe-dng": ["dng"],
|
|
701
724
|
"image/x-cmu-raster": ["ras"],
|
|
702
725
|
"image/x-cmx": ["cmx"],
|
|
703
726
|
"image/x-freehand": [
|
|
@@ -723,12 +746,13 @@ const types$1 = {
|
|
|
723
746
|
"image/x-xpixmap": ["xpm"],
|
|
724
747
|
"image/x-xwindowdump": ["xwd"],
|
|
725
748
|
"message/vnd.wfa.wsc": ["wsc"],
|
|
749
|
+
"model/vnd.bary": ["bary"],
|
|
726
750
|
"model/vnd.cld": ["cld"],
|
|
727
751
|
"model/vnd.collada+xml": ["dae"],
|
|
728
752
|
"model/vnd.dwf": ["dwf"],
|
|
729
753
|
"model/vnd.gdl": ["gdl"],
|
|
730
754
|
"model/vnd.gtw": ["gtw"],
|
|
731
|
-
"model/vnd.mts": ["mts"],
|
|
755
|
+
"model/vnd.mts": ["*mts"],
|
|
732
756
|
"model/vnd.opengex": ["ogex"],
|
|
733
757
|
"model/vnd.parasolid.transmit.binary": ["x_b"],
|
|
734
758
|
"model/vnd.parasolid.transmit.text": ["x_t"],
|
|
@@ -821,7 +845,7 @@ const types$1 = {
|
|
|
821
845
|
};
|
|
822
846
|
Object.freeze(types$1);
|
|
823
847
|
//#endregion
|
|
824
|
-
//#region ../../node_modules/.pnpm/mime@4.0
|
|
848
|
+
//#region ../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/types/standard.js
|
|
825
849
|
const types = {
|
|
826
850
|
"application/andrew-inset": ["ez"],
|
|
827
851
|
"application/appinstaller": ["appinstaller"],
|
|
@@ -852,6 +876,7 @@ const types = {
|
|
|
852
876
|
"application/dash+xml": ["mpd"],
|
|
853
877
|
"application/dash-patch+xml": ["mpp"],
|
|
854
878
|
"application/davmount+xml": ["davmount"],
|
|
879
|
+
"application/dicom": ["dcm"],
|
|
855
880
|
"application/docbook+xml": ["dbk"],
|
|
856
881
|
"application/dssc+der": ["dssc"],
|
|
857
882
|
"application/dssc+xml": ["xdssc"],
|
|
@@ -955,7 +980,9 @@ const types = {
|
|
|
955
980
|
"onetoc",
|
|
956
981
|
"onetoc2",
|
|
957
982
|
"onetmp",
|
|
958
|
-
"onepkg"
|
|
983
|
+
"onepkg",
|
|
984
|
+
"one",
|
|
985
|
+
"onea"
|
|
959
986
|
],
|
|
960
987
|
"application/oxps": ["oxps"],
|
|
961
988
|
"application/p2p-overlay+xml": ["relo"],
|
|
@@ -1066,6 +1093,7 @@ const types = {
|
|
|
1066
1093
|
"application/yang": ["yang"],
|
|
1067
1094
|
"application/yin+xml": ["yin"],
|
|
1068
1095
|
"application/zip": ["zip"],
|
|
1096
|
+
"application/zip+dotlottie": ["lottie"],
|
|
1069
1097
|
"audio/3gpp": ["*3gpp"],
|
|
1070
1098
|
"audio/aac": ["adts", "aac"],
|
|
1071
1099
|
"audio/adpcm": ["adp"],
|
|
@@ -1079,7 +1107,11 @@ const types = {
|
|
|
1079
1107
|
],
|
|
1080
1108
|
"audio/mobile-xmf": ["mxmf"],
|
|
1081
1109
|
"audio/mp3": ["*mp3"],
|
|
1082
|
-
"audio/mp4": [
|
|
1110
|
+
"audio/mp4": [
|
|
1111
|
+
"m4a",
|
|
1112
|
+
"mp4a",
|
|
1113
|
+
"m4b"
|
|
1114
|
+
],
|
|
1083
1115
|
"audio/mpeg": [
|
|
1084
1116
|
"mpga",
|
|
1085
1117
|
"mp2",
|
|
@@ -1123,19 +1155,21 @@ const types = {
|
|
|
1123
1155
|
"image/heif": ["heif"],
|
|
1124
1156
|
"image/heif-sequence": ["heifs"],
|
|
1125
1157
|
"image/hej2k": ["hej2"],
|
|
1126
|
-
"image/hsj2": ["hsj2"],
|
|
1127
1158
|
"image/ief": ["ief"],
|
|
1159
|
+
"image/jaii": ["jaii"],
|
|
1160
|
+
"image/jais": ["jais"],
|
|
1128
1161
|
"image/jls": ["jls"],
|
|
1129
1162
|
"image/jp2": ["jp2", "jpg2"],
|
|
1130
1163
|
"image/jpeg": [
|
|
1131
|
-
"jpeg",
|
|
1132
1164
|
"jpg",
|
|
1165
|
+
"jpeg",
|
|
1133
1166
|
"jpe"
|
|
1134
1167
|
],
|
|
1135
1168
|
"image/jph": ["jph"],
|
|
1136
1169
|
"image/jphc": ["jhc"],
|
|
1137
1170
|
"image/jpm": ["jpm", "jpgm"],
|
|
1138
1171
|
"image/jpx": ["jpx", "jpf"],
|
|
1172
|
+
"image/jxl": ["jxl"],
|
|
1139
1173
|
"image/jxr": ["jxr"],
|
|
1140
1174
|
"image/jxra": ["jxra"],
|
|
1141
1175
|
"image/jxrs": ["jxrs"],
|
|
@@ -1145,6 +1179,7 @@ const types = {
|
|
|
1145
1179
|
"image/jxss": ["jxss"],
|
|
1146
1180
|
"image/ktx": ["ktx"],
|
|
1147
1181
|
"image/ktx2": ["ktx2"],
|
|
1182
|
+
"image/pjpeg": ["jfif"],
|
|
1148
1183
|
"image/png": ["png"],
|
|
1149
1184
|
"image/sgi": ["sgi"],
|
|
1150
1185
|
"image/svg+xml": ["svg", "svgz"],
|
|
@@ -1158,7 +1193,12 @@ const types = {
|
|
|
1158
1193
|
"message/global-delivery-status": ["u8dsn"],
|
|
1159
1194
|
"message/global-disposition-notification": ["u8mdn"],
|
|
1160
1195
|
"message/global-headers": ["u8hdr"],
|
|
1161
|
-
"message/rfc822": [
|
|
1196
|
+
"message/rfc822": [
|
|
1197
|
+
"eml",
|
|
1198
|
+
"mime",
|
|
1199
|
+
"mht",
|
|
1200
|
+
"mhtml"
|
|
1201
|
+
],
|
|
1162
1202
|
"model/3mf": ["3mf"],
|
|
1163
1203
|
"model/gltf+json": ["gltf"],
|
|
1164
1204
|
"model/gltf-binary": ["glb"],
|
|
@@ -1172,6 +1212,13 @@ const types = {
|
|
|
1172
1212
|
"model/mtl": ["mtl"],
|
|
1173
1213
|
"model/obj": ["obj"],
|
|
1174
1214
|
"model/prc": ["prc"],
|
|
1215
|
+
"model/step": [
|
|
1216
|
+
"step",
|
|
1217
|
+
"stp",
|
|
1218
|
+
"stpnc",
|
|
1219
|
+
"p21",
|
|
1220
|
+
"210"
|
|
1221
|
+
],
|
|
1175
1222
|
"model/step+xml": ["stpx"],
|
|
1176
1223
|
"model/step+zip": ["stpz"],
|
|
1177
1224
|
"model/step-xml+zip": ["stpxz"],
|
|
@@ -1247,7 +1294,12 @@ const types = {
|
|
|
1247
1294
|
"video/jpeg": ["jpgv"],
|
|
1248
1295
|
"video/jpm": ["*jpm", "*jpgm"],
|
|
1249
1296
|
"video/mj2": ["mj2", "mjp2"],
|
|
1250
|
-
"video/mp2t": [
|
|
1297
|
+
"video/mp2t": [
|
|
1298
|
+
"ts",
|
|
1299
|
+
"m2t",
|
|
1300
|
+
"m2ts",
|
|
1301
|
+
"mts"
|
|
1302
|
+
],
|
|
1251
1303
|
"video/mp4": [
|
|
1252
1304
|
"mp4",
|
|
1253
1305
|
"mp4v",
|
|
@@ -1266,7 +1318,7 @@ const types = {
|
|
|
1266
1318
|
};
|
|
1267
1319
|
Object.freeze(types);
|
|
1268
1320
|
//#endregion
|
|
1269
|
-
//#region ../../node_modules/.pnpm/mime@4.0
|
|
1321
|
+
//#region ../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/src/Mime.js
|
|
1270
1322
|
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
1271
1323
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1272
1324
|
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");
|
|
@@ -1303,8 +1355,8 @@ var Mime = class {
|
|
|
1303
1355
|
}
|
|
1304
1356
|
getType(path) {
|
|
1305
1357
|
if (typeof path !== "string") return null;
|
|
1306
|
-
const last = path.replace(/^.*[/\\]
|
|
1307
|
-
const ext = last.replace(
|
|
1358
|
+
const last = path.replace(/^.*[/\\]/s, "").toLowerCase();
|
|
1359
|
+
const ext = last.replace(/^.*\./s, "").toLowerCase();
|
|
1308
1360
|
const hasPath = last.length < path.length;
|
|
1309
1361
|
if (!(ext.length < last.length - 1) && hasPath) return null;
|
|
1310
1362
|
return __classPrivateFieldGet(this, _Mime_extensionToType, "f").get(ext) ?? null;
|
|
@@ -1335,7 +1387,7 @@ var Mime = class {
|
|
|
1335
1387
|
};
|
|
1336
1388
|
_Mime_extensionToType = /* @__PURE__ */ new WeakMap(), _Mime_typeToExtension = /* @__PURE__ */ new WeakMap(), _Mime_typeToExtensions = /* @__PURE__ */ new WeakMap();
|
|
1337
1389
|
//#endregion
|
|
1338
|
-
//#region ../../node_modules/.pnpm/mime@4.0
|
|
1390
|
+
//#region ../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/src/index.js
|
|
1339
1391
|
var src_default = new Mime(types, types$1)._freeze();
|
|
1340
1392
|
//#endregion
|
|
1341
1393
|
//#region src/runtimeAwsConfig.ts
|
|
@@ -1386,7 +1438,76 @@ const streamToString = (stream) => {
|
|
|
1386
1438
|
//#region src/s3Database.ts
|
|
1387
1439
|
const DEFAULT_INVALIDATION_POLL_INTERVAL_MS = 2e3;
|
|
1388
1440
|
const DEFAULT_INVALIDATION_TIMEOUT_MS = 300 * 1e3;
|
|
1441
|
+
const S3_LIST_OBJECTS_CONCURRENCY = 4;
|
|
1442
|
+
const S3_DIRECTORY_DELIMITER = "/";
|
|
1389
1443
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1444
|
+
const getS3ErrorProperty = (error, key) => {
|
|
1445
|
+
if (typeof error !== "object" || error === null) return;
|
|
1446
|
+
const value = error[key];
|
|
1447
|
+
return typeof value === "string" ? value : void 0;
|
|
1448
|
+
};
|
|
1449
|
+
const isArchivedS3ObjectError = (error) => {
|
|
1450
|
+
if (!(error instanceof Error)) return false;
|
|
1451
|
+
return error.name === "InvalidObjectState" || getS3ErrorProperty(error, "Code") === "InvalidObjectState";
|
|
1452
|
+
};
|
|
1453
|
+
const createArchivedS3ObjectError = ({ bucket, key, error }) => {
|
|
1454
|
+
const storageClass = getS3ErrorProperty(error, "StorageClass") ?? "archived storage";
|
|
1455
|
+
const nextError = new Error(`S3 object "${key}" in bucket "${bucket}" is archived (${storageClass}) and cannot be read. Restore the object in S3 or exclude Hot Updater metadata from lifecycle archival: "**/target-app-versions.json" and "**/update.json".`, { cause: error });
|
|
1456
|
+
nextError.name = "S3ArchivedObjectError";
|
|
1457
|
+
return nextError;
|
|
1458
|
+
};
|
|
1459
|
+
function normalizeBasePath(basePath) {
|
|
1460
|
+
return basePath?.replace(/^\/+|\/+$/g, "") ?? "";
|
|
1461
|
+
}
|
|
1462
|
+
function createDatabaseKeyBuilder(basePath) {
|
|
1463
|
+
const normalizedBasePath = normalizeBasePath(basePath);
|
|
1464
|
+
const toStorageKey = (key) => [normalizedBasePath, key].filter(Boolean).join("/");
|
|
1465
|
+
const fromStorageKey = (key) => {
|
|
1466
|
+
if (!normalizedBasePath) return key;
|
|
1467
|
+
const prefix = `${normalizedBasePath}/`;
|
|
1468
|
+
return key.startsWith(prefix) ? key.slice(prefix.length) : key;
|
|
1469
|
+
};
|
|
1470
|
+
return {
|
|
1471
|
+
fromStorageKey,
|
|
1472
|
+
toStorageKey
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function normalizeDirectoryPrefix(prefix) {
|
|
1476
|
+
if (!prefix) return "";
|
|
1477
|
+
return prefix.endsWith(S3_DIRECTORY_DELIMITER) ? prefix : `${prefix}${S3_DIRECTORY_DELIMITER}`;
|
|
1478
|
+
}
|
|
1479
|
+
function getRelativeDirectoryPrefix(prefix, rootPrefix) {
|
|
1480
|
+
if (!rootPrefix) return prefix;
|
|
1481
|
+
return prefix.startsWith(rootPrefix) ? prefix.slice(rootPrefix.length) : prefix;
|
|
1482
|
+
}
|
|
1483
|
+
function getDirectoryDepth(prefix, rootPrefix) {
|
|
1484
|
+
return getRelativeDirectoryPrefix(prefix, rootPrefix).split(S3_DIRECTORY_DELIMITER).filter(Boolean).length;
|
|
1485
|
+
}
|
|
1486
|
+
function getLastDirectorySegment(prefix) {
|
|
1487
|
+
return prefix.split(S3_DIRECTORY_DELIMITER).filter(Boolean).at(-1);
|
|
1488
|
+
}
|
|
1489
|
+
function isPlatformDirectoryPrefix(prefix) {
|
|
1490
|
+
const lastSegment = getLastDirectorySegment(prefix);
|
|
1491
|
+
return lastSegment === "ios" || lastSegment === "android";
|
|
1492
|
+
}
|
|
1493
|
+
function isUpdateJsonKey(key) {
|
|
1494
|
+
return key.endsWith(`${S3_DIRECTORY_DELIMITER}update.json`);
|
|
1495
|
+
}
|
|
1496
|
+
async function mapWithConcurrency(items, concurrency, mapper) {
|
|
1497
|
+
const results = [];
|
|
1498
|
+
let nextIndex = 0;
|
|
1499
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
1500
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
1501
|
+
while (nextIndex < items.length) {
|
|
1502
|
+
const index = nextIndex;
|
|
1503
|
+
nextIndex += 1;
|
|
1504
|
+
const item = items[index];
|
|
1505
|
+
if (item === void 0) break;
|
|
1506
|
+
results[index] = await mapper(item, index);
|
|
1507
|
+
}
|
|
1508
|
+
}));
|
|
1509
|
+
return results.filter((result) => result !== void 0);
|
|
1510
|
+
}
|
|
1390
1511
|
/**
|
|
1391
1512
|
* Loads JSON data from S3.
|
|
1392
1513
|
* Returns null if NoSuchKey error occurs.
|
|
@@ -1402,6 +1523,11 @@ async function loadJsonFromS3(client, bucket, key) {
|
|
|
1402
1523
|
return JSON.parse(bodyContents);
|
|
1403
1524
|
} catch (e) {
|
|
1404
1525
|
if (e instanceof NoSuchKey) return null;
|
|
1526
|
+
if (isArchivedS3ObjectError(e)) throw createArchivedS3ObjectError({
|
|
1527
|
+
bucket,
|
|
1528
|
+
key,
|
|
1529
|
+
error: e
|
|
1530
|
+
});
|
|
1405
1531
|
throw e;
|
|
1406
1532
|
}
|
|
1407
1533
|
}
|
|
@@ -1409,31 +1535,47 @@ async function loadJsonFromS3(client, bucket, key) {
|
|
|
1409
1535
|
* Converts data to JSON string and uploads to S3.
|
|
1410
1536
|
*/
|
|
1411
1537
|
async function uploadJsonToS3(client, bucket, key, data) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
}).done();
|
|
1538
|
+
const Body = JSON.stringify(data);
|
|
1539
|
+
const ContentType = src_default.getType(key) ?? "application/json";
|
|
1540
|
+
await client.send(new PutObjectCommand({
|
|
1541
|
+
Bucket: bucket,
|
|
1542
|
+
Key: key,
|
|
1543
|
+
Body,
|
|
1544
|
+
ContentType,
|
|
1545
|
+
CacheControl: "max-age=31536000"
|
|
1546
|
+
}));
|
|
1422
1547
|
}
|
|
1423
|
-
async function listObjectsInS3(client, bucketName, prefix) {
|
|
1424
|
-
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1548
|
+
async function listObjectsInS3(client, bucketName, prefix, rootPrefix = "") {
|
|
1549
|
+
const normalizedRootPrefix = normalizeDirectoryPrefix(rootPrefix);
|
|
1550
|
+
const listPrefix = async (currentPrefix) => {
|
|
1551
|
+
let continuationToken;
|
|
1552
|
+
const keys = [];
|
|
1553
|
+
const commonPrefixes = /* @__PURE__ */ new Set();
|
|
1554
|
+
do {
|
|
1555
|
+
const response = await client.send(new ListObjectsV2Command({
|
|
1556
|
+
Bucket: bucketName,
|
|
1557
|
+
Prefix: currentPrefix,
|
|
1558
|
+
Delimiter: S3_DIRECTORY_DELIMITER,
|
|
1559
|
+
ContinuationToken: continuationToken
|
|
1560
|
+
}));
|
|
1561
|
+
const found = (response.Contents ?? []).map((item) => item.Key).filter((key) => !!key);
|
|
1562
|
+
keys.push(...found);
|
|
1563
|
+
for (const commonPrefix of response.CommonPrefixes ?? []) if (commonPrefix.Prefix) commonPrefixes.add(commonPrefix.Prefix);
|
|
1564
|
+
continuationToken = response.NextContinuationToken;
|
|
1565
|
+
} while (continuationToken);
|
|
1566
|
+
return {
|
|
1567
|
+
commonPrefixes: Array.from(commonPrefixes),
|
|
1568
|
+
keys
|
|
1569
|
+
};
|
|
1570
|
+
};
|
|
1571
|
+
const collectUpdateJsonKeys = async (currentPrefix) => {
|
|
1572
|
+
const { commonPrefixes, keys } = await listPrefix(currentPrefix);
|
|
1573
|
+
const depth = getDirectoryDepth(currentPrefix, normalizedRootPrefix);
|
|
1574
|
+
if (depth >= 2) return [...keys.filter(isUpdateJsonKey), ...commonPrefixes.map((commonPrefix) => `${commonPrefix}update.json`)];
|
|
1575
|
+
return (await mapWithConcurrency(depth === 1 ? commonPrefixes.filter(isPlatformDirectoryPrefix) : commonPrefixes, S3_LIST_OBJECTS_CONCURRENCY, (nextPrefix) => collectUpdateJsonKeys(nextPrefix))).flat();
|
|
1576
|
+
};
|
|
1577
|
+
const normalizedPrefix = normalizeDirectoryPrefix(prefix);
|
|
1578
|
+
return Array.from(new Set(await collectUpdateJsonKeys(normalizedPrefix)));
|
|
1437
1579
|
}
|
|
1438
1580
|
async function deleteObjectInS3(client, bucketName, key) {
|
|
1439
1581
|
await client.send(new DeleteObjectCommand({
|
|
@@ -1485,18 +1627,21 @@ async function invalidateCloudFront(client, distributionId, paths, options) {
|
|
|
1485
1627
|
const s3Database = createBlobDatabasePlugin({
|
|
1486
1628
|
name: "s3Database",
|
|
1487
1629
|
factory: (config) => {
|
|
1488
|
-
const { bucketName, cloudfrontDistributionId, apiBasePath = "/api/check-update", shouldWaitForInvalidation = false, ...s3Config } = config;
|
|
1630
|
+
const { basePath, bucketName, cloudfrontDistributionId, apiBasePath = "/api/check-update", shouldWaitForInvalidation = false, ...s3Config } = config;
|
|
1489
1631
|
const client = new S3Client(applyS3RuntimeAwsConfig(s3Config));
|
|
1632
|
+
const { fromStorageKey, toStorageKey } = createDatabaseKeyBuilder(basePath);
|
|
1633
|
+
const rootPrefix = toStorageKey("");
|
|
1490
1634
|
const cloudfrontClient = cloudfrontDistributionId ? new CloudFrontClient({
|
|
1491
1635
|
credentials: s3Config.credentials,
|
|
1492
1636
|
region: s3Config.region
|
|
1493
1637
|
}) : void 0;
|
|
1494
1638
|
return {
|
|
1495
1639
|
apiBasePath,
|
|
1496
|
-
listObjects: (prefix) => listObjectsInS3(client, bucketName, prefix),
|
|
1497
|
-
loadObject: (key) => loadJsonFromS3(client, bucketName, key),
|
|
1498
|
-
uploadObject: (key, data) => uploadJsonToS3(client, bucketName, key, data),
|
|
1499
|
-
deleteObject: (key) => deleteObjectInS3(client, bucketName, key),
|
|
1640
|
+
listObjects: (prefix) => listObjectsInS3(client, bucketName, toStorageKey(prefix), rootPrefix).then((keys) => keys.map(fromStorageKey)),
|
|
1641
|
+
loadObject: (key) => loadJsonFromS3(client, bucketName, toStorageKey(key)),
|
|
1642
|
+
uploadObject: (key, data) => uploadJsonToS3(client, bucketName, toStorageKey(key), data),
|
|
1643
|
+
deleteObject: (key) => deleteObjectInS3(client, bucketName, toStorageKey(key)),
|
|
1644
|
+
shouldSkipLoadObjectError: (error) => error instanceof Error && error.name === "S3ArchivedObjectError",
|
|
1500
1645
|
invalidatePaths: (pathsToInvalidate) => {
|
|
1501
1646
|
if (cloudfrontClient && cloudfrontDistributionId && pathsToInvalidate.length > 0) return invalidateCloudFront(cloudfrontClient, cloudfrontDistributionId, pathsToInvalidate, { shouldWaitForInvalidation });
|
|
1502
1647
|
return Promise.resolve();
|