@hot-updater/plugin-core 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 +455 -174
- package/dist/index.d.cts +133 -4
- package/dist/index.d.ts +133 -4
- package/dist/index.js +287 -19
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -2,11 +2,14 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import process$1 from "node:process";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import tty from "node:tty";
|
|
5
|
-
import
|
|
5
|
+
import mime from "mime";
|
|
6
6
|
import path from "path";
|
|
7
|
+
import fs from "fs/promises";
|
|
7
8
|
import fs$1 from "fs";
|
|
8
9
|
import fg from "fast-glob";
|
|
9
10
|
import semver from "semver";
|
|
11
|
+
import * as tar from "tar";
|
|
12
|
+
import { brotliCompressSync, constants } from "zlib";
|
|
10
13
|
import { cosmiconfig, cosmiconfigSync } from "cosmiconfig";
|
|
11
14
|
import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
|
|
12
15
|
import { transform } from "oxc-transform";
|
|
@@ -1553,6 +1556,56 @@ function calculatePagination(total, options) {
|
|
|
1553
1556
|
};
|
|
1554
1557
|
}
|
|
1555
1558
|
|
|
1559
|
+
//#endregion
|
|
1560
|
+
//#region src/compressionFormat.ts
|
|
1561
|
+
/**
|
|
1562
|
+
* Compression formats registry
|
|
1563
|
+
* Add new formats here to support additional compression types
|
|
1564
|
+
*/
|
|
1565
|
+
const COMPRESSION_FORMATS = {
|
|
1566
|
+
zip: {
|
|
1567
|
+
format: "zip",
|
|
1568
|
+
fileExtension: ".zip",
|
|
1569
|
+
mimeType: "application/zip"
|
|
1570
|
+
},
|
|
1571
|
+
"tar.br": {
|
|
1572
|
+
format: "tar.br",
|
|
1573
|
+
fileExtension: ".tar.br",
|
|
1574
|
+
mimeType: "application/x-tar"
|
|
1575
|
+
},
|
|
1576
|
+
"tar.gz": {
|
|
1577
|
+
format: "tar.gz",
|
|
1578
|
+
fileExtension: ".tar.gz",
|
|
1579
|
+
mimeType: "application/x-tar"
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
/**
|
|
1583
|
+
* Detects compression format from filename
|
|
1584
|
+
* @param filename The filename to detect format from
|
|
1585
|
+
* @returns Compression format information
|
|
1586
|
+
*/
|
|
1587
|
+
function detectCompressionFormat(filename) {
|
|
1588
|
+
for (const info of Object.values(COMPRESSION_FORMATS)) if (filename.endsWith(info.fileExtension)) return info;
|
|
1589
|
+
return COMPRESSION_FORMATS.zip;
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Gets MIME type for a filename
|
|
1593
|
+
* @param filename The filename to get MIME type for
|
|
1594
|
+
* @returns MIME type string
|
|
1595
|
+
*/
|
|
1596
|
+
function getCompressionMimeType(filename) {
|
|
1597
|
+
return detectCompressionFormat(filename).mimeType;
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Gets Content-Type for a bundle file with 3-tier fallback
|
|
1601
|
+
* @param bundlePath The bundle file path
|
|
1602
|
+
* @returns Content-Type string (never undefined, falls back to application/octet-stream)
|
|
1603
|
+
*/
|
|
1604
|
+
function getContentType(bundlePath) {
|
|
1605
|
+
const filename = path.basename(bundlePath);
|
|
1606
|
+
return mime.getType(bundlePath) ?? getCompressionMimeType(filename) ?? "application/octet-stream";
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1556
1609
|
//#endregion
|
|
1557
1610
|
//#region ../../node_modules/.pnpm/workspace-tools@0.36.4/node_modules/workspace-tools/lib/graph/getPackageDependencies.js
|
|
1558
1611
|
var require_getPackageDependencies = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/workspace-tools@0.36.4/node_modules/workspace-tools/lib/graph/getPackageDependencies.js": ((exports) => {
|
|
@@ -8462,12 +8515,12 @@ var require_scan = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/picoma
|
|
|
8462
8515
|
//#endregion
|
|
8463
8516
|
//#region ../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/parse.js
|
|
8464
8517
|
var require_parse = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/parse.js": ((exports, module) => {
|
|
8465
|
-
const constants$
|
|
8518
|
+
const constants$3 = require_constants$1();
|
|
8466
8519
|
const utils$30 = require_utils$1();
|
|
8467
8520
|
/**
|
|
8468
8521
|
* Constants
|
|
8469
8522
|
*/
|
|
8470
|
-
const { MAX_LENGTH, POSIX_REGEX_SOURCE, REGEX_NON_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_BACKREF, REPLACEMENTS } = constants$
|
|
8523
|
+
const { MAX_LENGTH, POSIX_REGEX_SOURCE, REGEX_NON_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_BACKREF, REPLACEMENTS } = constants$3;
|
|
8471
8524
|
/**
|
|
8472
8525
|
* Helpers
|
|
8473
8526
|
*/
|
|
@@ -8509,8 +8562,8 @@ var require_parse = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/picom
|
|
|
8509
8562
|
const tokens = [bos];
|
|
8510
8563
|
const capture = opts.capture ? "" : "?:";
|
|
8511
8564
|
const win32$1 = utils$30.isWindows(options);
|
|
8512
|
-
const PLATFORM_CHARS = constants$
|
|
8513
|
-
const EXTGLOB_CHARS = constants$
|
|
8565
|
+
const PLATFORM_CHARS = constants$3.globChars(win32$1);
|
|
8566
|
+
const EXTGLOB_CHARS = constants$3.extglobChars(PLATFORM_CHARS);
|
|
8514
8567
|
const { DOT_LITERAL: DOT_LITERAL$1, PLUS_LITERAL: PLUS_LITERAL$1, SLASH_LITERAL: SLASH_LITERAL$1, ONE_CHAR: ONE_CHAR$1, DOTS_SLASH: DOTS_SLASH$1, NO_DOT, NO_DOT_SLASH, NO_DOTS_SLASH, QMARK: QMARK$1, QMARK_NO_DOT, STAR, START_ANCHOR: START_ANCHOR$1 } = PLATFORM_CHARS;
|
|
8515
8568
|
const globstar = (opts$1) => {
|
|
8516
8569
|
return `(${capture}(?:(?!${START_ANCHOR$1}${opts$1.dot ? DOTS_SLASH$1 : DOT_LITERAL$1}).)*?)`;
|
|
@@ -9281,7 +9334,7 @@ var require_parse = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/picom
|
|
|
9281
9334
|
if (len > max) throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
|
9282
9335
|
input = REPLACEMENTS[input] || input;
|
|
9283
9336
|
const win32$1 = utils$30.isWindows(options);
|
|
9284
|
-
const { DOT_LITERAL: DOT_LITERAL$1, SLASH_LITERAL: SLASH_LITERAL$1, ONE_CHAR: ONE_CHAR$1, DOTS_SLASH: DOTS_SLASH$1, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR: START_ANCHOR$1 } = constants$
|
|
9337
|
+
const { DOT_LITERAL: DOT_LITERAL$1, SLASH_LITERAL: SLASH_LITERAL$1, ONE_CHAR: ONE_CHAR$1, DOTS_SLASH: DOTS_SLASH$1, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR: START_ANCHOR$1 } = constants$3.globChars(win32$1);
|
|
9285
9338
|
const nodot = opts.dot ? NO_DOTS : NO_DOT;
|
|
9286
9339
|
const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
|
|
9287
9340
|
const capture = opts.capture ? "" : "?:";
|
|
@@ -9328,7 +9381,7 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm
|
|
|
9328
9381
|
const scan = require_scan();
|
|
9329
9382
|
const parse = require_parse();
|
|
9330
9383
|
const utils$29 = require_utils$1();
|
|
9331
|
-
const constants$
|
|
9384
|
+
const constants$2 = require_constants$1();
|
|
9332
9385
|
const isObject$1 = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
9333
9386
|
/**
|
|
9334
9387
|
* Creates a matcher function from one or more glob patterns. The
|
|
@@ -9608,7 +9661,7 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm
|
|
|
9608
9661
|
* Picomatch constants.
|
|
9609
9662
|
* @return {Object}
|
|
9610
9663
|
*/
|
|
9611
|
-
picomatch$1.constants = constants$
|
|
9664
|
+
picomatch$1.constants = constants$2;
|
|
9612
9665
|
/**
|
|
9613
9666
|
* Expose "picomatch"
|
|
9614
9667
|
*/
|
|
@@ -11058,7 +11111,7 @@ var require_lockfile$1 = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/
|
|
|
11058
11111
|
};
|
|
11059
11112
|
})();
|
|
11060
11113
|
exports$1.getFirstSuitableFolder = (() => {
|
|
11061
|
-
var _ref36 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths, mode = constants$
|
|
11114
|
+
var _ref36 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths, mode = constants$4.W_OK | constants$4.X_OK) {
|
|
11062
11115
|
const result = {
|
|
11063
11116
|
skipped: [],
|
|
11064
11117
|
folder: null
|
|
@@ -11146,7 +11199,7 @@ var require_lockfile$1 = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/
|
|
|
11146
11199
|
function _interopRequireDefault(obj) {
|
|
11147
11200
|
return obj && obj.__esModule ? obj : { default: obj };
|
|
11148
11201
|
}
|
|
11149
|
-
const constants$
|
|
11202
|
+
const constants$4 = exports$1.constants = typeof (_fs || _load_fs()).default.constants !== "undefined" ? (_fs || _load_fs()).default.constants : {
|
|
11150
11203
|
R_OK: (_fs || _load_fs()).default.R_OK,
|
|
11151
11204
|
W_OK: (_fs || _load_fs()).default.W_OK,
|
|
11152
11205
|
X_OK: (_fs || _load_fs()).default.X_OK
|
|
@@ -17768,9 +17821,15 @@ function removeBundleInternalKeys(bundle) {
|
|
|
17768
17821
|
const { _updateJsonKey, _oldUpdateJsonKey,...pureBundle } = bundle;
|
|
17769
17822
|
return pureBundle;
|
|
17770
17823
|
}
|
|
17824
|
+
function normalizeTargetAppVersion(version) {
|
|
17825
|
+
if (!version) return null;
|
|
17826
|
+
return version.replace(/\s+/g, "");
|
|
17827
|
+
}
|
|
17771
17828
|
function isExactVersion(version) {
|
|
17772
17829
|
if (!version) return false;
|
|
17773
|
-
|
|
17830
|
+
const normalized = normalizeTargetAppVersion(version);
|
|
17831
|
+
if (!normalized) return false;
|
|
17832
|
+
return semver.valid(normalized) !== null;
|
|
17774
17833
|
}
|
|
17775
17834
|
/**
|
|
17776
17835
|
* Get all normalized semver versions for a version string.
|
|
@@ -17782,8 +17841,9 @@ function isExactVersion(version) {
|
|
|
17782
17841
|
* - "1.2.3" generates ["1.2.3"]
|
|
17783
17842
|
*/
|
|
17784
17843
|
function getSemverNormalizedVersions(version) {
|
|
17785
|
-
const
|
|
17786
|
-
|
|
17844
|
+
const normalized = normalizeTargetAppVersion(version) || version;
|
|
17845
|
+
const coerced = semver.coerce(normalized);
|
|
17846
|
+
if (!coerced) return [normalized];
|
|
17787
17847
|
const versions = /* @__PURE__ */ new Set();
|
|
17788
17848
|
versions.add(coerced.version);
|
|
17789
17849
|
if (coerced.patch === 0) versions.add(`${coerced.major}.${coerced.minor}`);
|
|
@@ -17903,7 +17963,7 @@ const createBlobDatabasePlugin = ({ name, getContext, listObjects, loadObject, u
|
|
|
17903
17963
|
for (const { operation, data } of changedSets) {
|
|
17904
17964
|
if (data.targetAppVersion !== void 0) isTargetAppVersionChanged = true;
|
|
17905
17965
|
if (operation === "insert") {
|
|
17906
|
-
const target = data.targetAppVersion ?? data.fingerprintHash;
|
|
17966
|
+
const target = normalizeTargetAppVersion(data.targetAppVersion) ?? data.fingerprintHash;
|
|
17907
17967
|
if (!target) throw new Error("target not found");
|
|
17908
17968
|
const key = `${data.channel}/${data.platform}/${target}/update.json`;
|
|
17909
17969
|
const bundleWithKey = {
|
|
@@ -17947,7 +18007,7 @@ const createBlobDatabasePlugin = ({ name, getContext, listObjects, loadObject, u
|
|
|
17947
18007
|
if (operation === "update") {
|
|
17948
18008
|
const newChannel = data.channel !== void 0 ? data.channel : bundle.channel;
|
|
17949
18009
|
const newPlatform = data.platform !== void 0 ? data.platform : bundle.platform;
|
|
17950
|
-
const target = data.fingerprintHash ?? bundle.fingerprintHash ?? data.targetAppVersion ?? bundle.targetAppVersion;
|
|
18010
|
+
const target = data.fingerprintHash ?? bundle.fingerprintHash ?? normalizeTargetAppVersion(data.targetAppVersion) ?? normalizeTargetAppVersion(bundle.targetAppVersion);
|
|
17951
18011
|
if (!target) throw new Error("target not found");
|
|
17952
18012
|
const newKey = `${newChannel}/${newPlatform}/${target}/update.json`;
|
|
17953
18013
|
if (newKey !== bundle._updateJsonKey) {
|
|
@@ -18047,7 +18107,9 @@ const createBlobDatabasePlugin = ({ name, getContext, listObjects, loadObject, u
|
|
|
18047
18107
|
for (const path$4 of updatedPaths) updatedTargetFilePaths.add(path$4);
|
|
18048
18108
|
}
|
|
18049
18109
|
for (const path$4 of updatedTargetFilePaths) pathsToInvalidate.add(path$4);
|
|
18050
|
-
|
|
18110
|
+
const encondedPaths = /* @__PURE__ */ new Set();
|
|
18111
|
+
for (const path$4 of pathsToInvalidate) encondedPaths.add(encodeURI(path$4));
|
|
18112
|
+
await invalidatePaths(context, Array.from(encondedPaths));
|
|
18051
18113
|
pendingBundlesMap.clear();
|
|
18052
18114
|
hooks?.onDatabaseUpdated?.();
|
|
18053
18115
|
}
|
|
@@ -18060,6 +18122,156 @@ const createStorageKeyBuilder = (basePath) => (...args) => {
|
|
|
18060
18122
|
return [basePath || "", ...args].filter(Boolean).join("/");
|
|
18061
18123
|
};
|
|
18062
18124
|
|
|
18125
|
+
//#endregion
|
|
18126
|
+
//#region src/createTarBr.ts
|
|
18127
|
+
const createTarBrTargetFiles = async ({ outfile, targetFiles }) => {
|
|
18128
|
+
await fs.rm(outfile, { force: true });
|
|
18129
|
+
const tmpDir = path.join(path.dirname(outfile), `.tmp-tar-${Date.now()}`);
|
|
18130
|
+
await fs.mkdir(tmpDir, { recursive: true });
|
|
18131
|
+
try {
|
|
18132
|
+
for (const target of targetFiles) {
|
|
18133
|
+
const sourcePath = target.path;
|
|
18134
|
+
const destPath = path.join(tmpDir, target.name);
|
|
18135
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
18136
|
+
if ((await fs.stat(sourcePath)).isDirectory()) await copyDir$1(sourcePath, destPath);
|
|
18137
|
+
else await fs.copyFile(sourcePath, destPath);
|
|
18138
|
+
}
|
|
18139
|
+
const tmpTarFile = outfile.replace(/\.tar\.br$/, ".tar");
|
|
18140
|
+
await tar.create({
|
|
18141
|
+
file: tmpTarFile,
|
|
18142
|
+
cwd: tmpDir,
|
|
18143
|
+
portable: true,
|
|
18144
|
+
mtime: /* @__PURE__ */ new Date(0),
|
|
18145
|
+
gzip: false
|
|
18146
|
+
}, await fs.readdir(tmpDir));
|
|
18147
|
+
const compressedData = brotliCompressSync(await fs.readFile(tmpTarFile), { params: {
|
|
18148
|
+
[constants.BROTLI_PARAM_QUALITY]: 11,
|
|
18149
|
+
[constants.BROTLI_PARAM_LGWIN]: 24
|
|
18150
|
+
} });
|
|
18151
|
+
await fs.mkdir(path.dirname(outfile), { recursive: true });
|
|
18152
|
+
await fs.writeFile(outfile, compressedData);
|
|
18153
|
+
await fs.rm(tmpTarFile, { force: true });
|
|
18154
|
+
return outfile;
|
|
18155
|
+
} finally {
|
|
18156
|
+
await fs.rm(tmpDir, {
|
|
18157
|
+
recursive: true,
|
|
18158
|
+
force: true
|
|
18159
|
+
});
|
|
18160
|
+
}
|
|
18161
|
+
};
|
|
18162
|
+
async function copyDir$1(src, dest) {
|
|
18163
|
+
await fs.mkdir(dest, { recursive: true });
|
|
18164
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
18165
|
+
for (const entry of entries) {
|
|
18166
|
+
const srcPath = path.join(src, entry.name);
|
|
18167
|
+
const destPath = path.join(dest, entry.name);
|
|
18168
|
+
if (entry.isDirectory()) await copyDir$1(srcPath, destPath);
|
|
18169
|
+
else await fs.copyFile(srcPath, destPath);
|
|
18170
|
+
}
|
|
18171
|
+
}
|
|
18172
|
+
const createTarBr = async ({ outfile, targetDir, excludeExts = [] }) => {
|
|
18173
|
+
await fs.rm(outfile, { force: true });
|
|
18174
|
+
const tmpTarFile = outfile.replace(/\.tar\.br$/, ".tar");
|
|
18175
|
+
async function getFiles(dir, baseDir = "") {
|
|
18176
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
18177
|
+
const files = [];
|
|
18178
|
+
for (const entry of entries) {
|
|
18179
|
+
if (excludeExts.some((pattern) => entry.name.includes(pattern))) continue;
|
|
18180
|
+
const fullPath = path.join(dir, entry.name);
|
|
18181
|
+
const relativePath = path.join(baseDir, entry.name);
|
|
18182
|
+
if (entry.isDirectory()) {
|
|
18183
|
+
const subFiles = await getFiles(fullPath, relativePath);
|
|
18184
|
+
files.push(...subFiles);
|
|
18185
|
+
} else files.push(relativePath);
|
|
18186
|
+
}
|
|
18187
|
+
return files;
|
|
18188
|
+
}
|
|
18189
|
+
const filesToInclude = await getFiles(targetDir);
|
|
18190
|
+
filesToInclude.sort();
|
|
18191
|
+
await tar.create({
|
|
18192
|
+
file: tmpTarFile,
|
|
18193
|
+
cwd: targetDir,
|
|
18194
|
+
portable: true,
|
|
18195
|
+
mtime: /* @__PURE__ */ new Date(0),
|
|
18196
|
+
gzip: false
|
|
18197
|
+
}, filesToInclude);
|
|
18198
|
+
const compressedData = brotliCompressSync(await fs.readFile(tmpTarFile), { params: {
|
|
18199
|
+
[constants.BROTLI_PARAM_QUALITY]: 11,
|
|
18200
|
+
[constants.BROTLI_PARAM_LGWIN]: 24
|
|
18201
|
+
} });
|
|
18202
|
+
await fs.writeFile(outfile, compressedData);
|
|
18203
|
+
await fs.rm(tmpTarFile, { force: true });
|
|
18204
|
+
return outfile;
|
|
18205
|
+
};
|
|
18206
|
+
|
|
18207
|
+
//#endregion
|
|
18208
|
+
//#region src/createTarGz.ts
|
|
18209
|
+
const createTarGzTargetFiles = async ({ outfile, targetFiles }) => {
|
|
18210
|
+
await fs.rm(outfile, { force: true });
|
|
18211
|
+
const tmpDir = path.join(path.dirname(outfile), `.tmp-tar-${Date.now()}`);
|
|
18212
|
+
await fs.mkdir(tmpDir, { recursive: true });
|
|
18213
|
+
try {
|
|
18214
|
+
for (const target of targetFiles) {
|
|
18215
|
+
const sourcePath = target.path;
|
|
18216
|
+
const destPath = path.join(tmpDir, target.name);
|
|
18217
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
18218
|
+
if ((await fs.stat(sourcePath)).isDirectory()) await copyDir(sourcePath, destPath);
|
|
18219
|
+
else await fs.copyFile(sourcePath, destPath);
|
|
18220
|
+
}
|
|
18221
|
+
await fs.mkdir(path.dirname(outfile), { recursive: true });
|
|
18222
|
+
await tar.create({
|
|
18223
|
+
file: outfile,
|
|
18224
|
+
cwd: tmpDir,
|
|
18225
|
+
portable: true,
|
|
18226
|
+
mtime: /* @__PURE__ */ new Date(0),
|
|
18227
|
+
gzip: true
|
|
18228
|
+
}, await fs.readdir(tmpDir));
|
|
18229
|
+
return outfile;
|
|
18230
|
+
} finally {
|
|
18231
|
+
await fs.rm(tmpDir, {
|
|
18232
|
+
recursive: true,
|
|
18233
|
+
force: true
|
|
18234
|
+
});
|
|
18235
|
+
}
|
|
18236
|
+
};
|
|
18237
|
+
async function copyDir(src, dest) {
|
|
18238
|
+
await fs.mkdir(dest, { recursive: true });
|
|
18239
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
18240
|
+
for (const entry of entries) {
|
|
18241
|
+
const srcPath = path.join(src, entry.name);
|
|
18242
|
+
const destPath = path.join(dest, entry.name);
|
|
18243
|
+
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
18244
|
+
else await fs.copyFile(srcPath, destPath);
|
|
18245
|
+
}
|
|
18246
|
+
}
|
|
18247
|
+
const createTarGz = async ({ outfile, targetDir, excludeExts = [] }) => {
|
|
18248
|
+
await fs.rm(outfile, { force: true });
|
|
18249
|
+
async function getFiles(dir, baseDir = "") {
|
|
18250
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
18251
|
+
const files = [];
|
|
18252
|
+
for (const entry of entries) {
|
|
18253
|
+
if (excludeExts.some((pattern) => entry.name.includes(pattern))) continue;
|
|
18254
|
+
const fullPath = path.join(dir, entry.name);
|
|
18255
|
+
const relativePath = path.join(baseDir, entry.name);
|
|
18256
|
+
if (entry.isDirectory()) {
|
|
18257
|
+
const subFiles = await getFiles(fullPath, relativePath);
|
|
18258
|
+
files.push(...subFiles);
|
|
18259
|
+
} else files.push(relativePath);
|
|
18260
|
+
}
|
|
18261
|
+
return files;
|
|
18262
|
+
}
|
|
18263
|
+
const filesToInclude = await getFiles(targetDir);
|
|
18264
|
+
filesToInclude.sort();
|
|
18265
|
+
await tar.create({
|
|
18266
|
+
file: outfile,
|
|
18267
|
+
cwd: targetDir,
|
|
18268
|
+
portable: true,
|
|
18269
|
+
mtime: /* @__PURE__ */ new Date(0),
|
|
18270
|
+
gzip: true
|
|
18271
|
+
}, filesToInclude);
|
|
18272
|
+
return outfile;
|
|
18273
|
+
};
|
|
18274
|
+
|
|
18063
18275
|
//#endregion
|
|
18064
18276
|
//#region ../../node_modules/.pnpm/process-nextick-args@2.0.1/node_modules/process-nextick-args/index.js
|
|
18065
18277
|
var require_process_nextick_args = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/process-nextick-args@2.0.1/node_modules/process-nextick-args/index.js": ((exports, module) => {
|
|
@@ -25511,9 +25723,9 @@ var require_pako = /* @__PURE__ */ __commonJS({ "../../node_modules/.pnpm/pako@1
|
|
|
25511
25723
|
var assign = require_common().assign;
|
|
25512
25724
|
var deflate = require_deflate();
|
|
25513
25725
|
var inflate = require_inflate();
|
|
25514
|
-
var constants = require_constants();
|
|
25726
|
+
var constants$1 = require_constants();
|
|
25515
25727
|
var pako$1 = {};
|
|
25516
|
-
assign(pako$1, deflate, inflate, constants);
|
|
25728
|
+
assign(pako$1, deflate, inflate, constants$1);
|
|
25517
25729
|
module.exports = pako$1;
|
|
25518
25730
|
}) });
|
|
25519
25731
|
|
|
@@ -26893,6 +27105,28 @@ const createZip = async ({ outfile, targetDir, excludeExts = [] }) => {
|
|
|
26893
27105
|
return outfile;
|
|
26894
27106
|
};
|
|
26895
27107
|
|
|
27108
|
+
//#endregion
|
|
27109
|
+
//#region src/semverSatisfies.ts
|
|
27110
|
+
const semverSatisfies = (targetAppVersion, currentVersion) => {
|
|
27111
|
+
const currentCoerce = semver.coerce(currentVersion);
|
|
27112
|
+
if (!currentCoerce) return false;
|
|
27113
|
+
return semver.satisfies(currentCoerce.version, targetAppVersion);
|
|
27114
|
+
};
|
|
27115
|
+
|
|
27116
|
+
//#endregion
|
|
27117
|
+
//#region src/filterCompatibleAppVersions.ts
|
|
27118
|
+
/**
|
|
27119
|
+
* Filters target app versions that are compatible with the current app version.
|
|
27120
|
+
* Returns only versions that are compatible with the current version according to semver rules.
|
|
27121
|
+
*
|
|
27122
|
+
* @param targetAppVersionList - List of target app versions to filter
|
|
27123
|
+
* @param currentVersion - Current app version
|
|
27124
|
+
* @returns Array of target app versions compatible with the current version
|
|
27125
|
+
*/
|
|
27126
|
+
const filterCompatibleAppVersions = (targetAppVersionList, currentVersion) => {
|
|
27127
|
+
return targetAppVersionList.filter((version) => semverSatisfies(version, currentVersion)).sort((a, b) => b.localeCompare(a));
|
|
27128
|
+
};
|
|
27129
|
+
|
|
26896
27130
|
//#endregion
|
|
26897
27131
|
//#region src/generateMinBundleId.ts
|
|
26898
27132
|
const generateMinBundleId = () => {
|
|
@@ -26939,6 +27173,7 @@ const getDefaultConfig = () => {
|
|
|
26939
27173
|
return {
|
|
26940
27174
|
releaseChannel: "production",
|
|
26941
27175
|
updateStrategy: "appVersion",
|
|
27176
|
+
compressStrategy: "zip",
|
|
26942
27177
|
fingerprint: { extraSources: [] },
|
|
26943
27178
|
console: { port: 1422 },
|
|
26944
27179
|
platform: getDefaultPlatformConfig(),
|
|
@@ -27050,6 +27285,39 @@ const makeEnv = async (newEnvVars, filePath = ".env.hotupdater") => {
|
|
|
27050
27285
|
}
|
|
27051
27286
|
};
|
|
27052
27287
|
|
|
27288
|
+
//#endregion
|
|
27289
|
+
//#region src/parseStorageUri.ts
|
|
27290
|
+
/**
|
|
27291
|
+
* Parses a storage URI and validates the protocol.
|
|
27292
|
+
*
|
|
27293
|
+
* @param storageUri - The storage URI to parse (e.g., "s3://bucket/path/to/file")
|
|
27294
|
+
* @param expectedProtocol - The expected protocol without colon (e.g., "s3", "r2", "gs")
|
|
27295
|
+
* @returns Parsed storage URI components
|
|
27296
|
+
* @throws Error if the URI is invalid or protocol doesn't match
|
|
27297
|
+
*
|
|
27298
|
+
* @example
|
|
27299
|
+
* ```typescript
|
|
27300
|
+
* const { bucket, key } = parseStorageUri("s3://my-bucket/path/to/file.zip", "s3");
|
|
27301
|
+
* // bucket: "my-bucket"
|
|
27302
|
+
* // key: "path/to/file.zip"
|
|
27303
|
+
* ```
|
|
27304
|
+
*/
|
|
27305
|
+
function parseStorageUri(storageUri, expectedProtocol) {
|
|
27306
|
+
try {
|
|
27307
|
+
const url = new URL(storageUri);
|
|
27308
|
+
const protocol = url.protocol.replace(":", "");
|
|
27309
|
+
if (protocol !== expectedProtocol) throw new Error(`Invalid storage URI protocol. Expected ${expectedProtocol}, got ${protocol}`);
|
|
27310
|
+
return {
|
|
27311
|
+
protocol,
|
|
27312
|
+
bucket: url.hostname,
|
|
27313
|
+
key: url.pathname.slice(1)
|
|
27314
|
+
};
|
|
27315
|
+
} catch (error) {
|
|
27316
|
+
if (error instanceof TypeError) throw new Error(`Invalid storage URI format: ${storageUri}`);
|
|
27317
|
+
throw error;
|
|
27318
|
+
}
|
|
27319
|
+
}
|
|
27320
|
+
|
|
27053
27321
|
//#endregion
|
|
27054
27322
|
//#region src/transformEnv.ts
|
|
27055
27323
|
const transformEnv = (filename, env$2) => {
|
|
@@ -27078,4 +27346,4 @@ function transformTemplate(templateString, values) {
|
|
|
27078
27346
|
}
|
|
27079
27347
|
|
|
27080
27348
|
//#endregion
|
|
27081
|
-
export { ConfigBuilder, banner, calculatePagination, copyDirToTmp, createBlobDatabasePlugin, createDatabasePlugin, createStorageKeyBuilder, createZip, createZipTargetFiles, generateMinBundleId, getCwd, link, loadConfig, loadConfigSync, log, makeEnv, printBanner, transformEnv, transformTemplate };
|
|
27349
|
+
export { ConfigBuilder, banner, calculatePagination, copyDirToTmp, createBlobDatabasePlugin, createDatabasePlugin, createStorageKeyBuilder, createTarBr, createTarBrTargetFiles, createTarGz, createTarGzTargetFiles, createZip, createZipTargetFiles, detectCompressionFormat, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, getCwd, link, loadConfig, loadConfigSync, log, makeEnv, parseStorageUri, printBanner, semverSatisfies, transformEnv, transformTemplate };
|
package/package.json
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/plugin-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
7
|
-
"main": "dist/index.cjs",
|
|
8
|
-
"module": "dist/index.js",
|
|
9
|
-
"types": "dist/index.d.
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.cts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
14
|
},
|
|
15
|
-
"./
|
|
16
|
-
"import": "./src/test-utils/index.ts",
|
|
17
|
-
"require": "./src/test-utils/index.ts"
|
|
18
|
-
}
|
|
15
|
+
"./package.json": "./package.json"
|
|
19
16
|
},
|
|
20
17
|
"files": [
|
|
21
18
|
"dist",
|
|
@@ -45,9 +42,12 @@
|
|
|
45
42
|
"cosmiconfig": "9.0.0",
|
|
46
43
|
"cosmiconfig-typescript-loader": "5.0.0",
|
|
47
44
|
"fast-glob": "3.3.3",
|
|
45
|
+
"mime": "^4.0.4",
|
|
48
46
|
"oxc-transform": "0.82.1",
|
|
49
47
|
"semver": "^7.7.2",
|
|
50
|
-
"
|
|
48
|
+
"tar": "^7.5.1",
|
|
49
|
+
"zlib": "^1.0.5",
|
|
50
|
+
"@hot-updater/core": "0.21.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "^20",
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
"picocolors": "1.1.1",
|
|
59
59
|
"typescript": "5.8.2",
|
|
60
60
|
"workspace-tools": "^0.36.4",
|
|
61
|
-
"@hot-updater/plugin-core": "0.
|
|
61
|
+
"@hot-updater/plugin-core": "0.21.0",
|
|
62
|
+
"@hot-updater/test-utils": "0.21.0"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"build": "tsdown",
|