@otakit/cli 1.5.0 → 1.6.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/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +2 -0
- package/dist/commands/upload.js.map +1 -1
- package/dist/index.js +190 -100
- package/dist/index.js.map +4 -4
- package/dist/lib/artifact-preflight.d.ts +21 -0
- package/dist/lib/artifact-preflight.d.ts.map +1 -0
- package/dist/lib/artifact-preflight.js +74 -0
- package/dist/lib/artifact-preflight.js.map +1 -0
- package/dist/lib/upload-workflow.d.ts +2 -0
- package/dist/lib/upload-workflow.d.ts.map +1 -1
- package/dist/lib/upload-workflow.js +9 -1
- package/dist/lib/upload-workflow.js.map +1 -1
- package/dist/lib/zip.d.ts.map +1 -1
- package/dist/lib/zip.js +3 -0
- package/dist/lib/zip.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4EpC,eAAO,MAAM,aAAa,SA8KtB,CAAC"}
|
package/dist/commands/upload.js
CHANGED
|
@@ -40,6 +40,7 @@ export const uploadCommand = new Command('upload')
|
|
|
40
40
|
.option('--server <url>', 'Server URL override')
|
|
41
41
|
.option('--version <version>', 'Version string (default: OTAKIT_VERSION, then auto-generated)')
|
|
42
42
|
.option('--strict-version', 'Require explicit version (--version or OTAKIT_VERSION)')
|
|
43
|
+
.option('--strict-artifacts', 'Fail before uploading on large bundles or native installer artifacts')
|
|
43
44
|
.option('--release [channel]', 'Release after upload (base channel if omitted)')
|
|
44
45
|
.option('--strategy <strategy>', 'Upload strategy: "zip" (single archive, default) or "deltas" (per-file objects)')
|
|
45
46
|
.option('--fail-on-incompatible', 'Exit non-zero when native compatibility check fails')
|
|
@@ -131,6 +132,7 @@ export const uploadCommand = new Command('upload')
|
|
|
131
132
|
autoRevertRatePercent,
|
|
132
133
|
autoRevertMinSample,
|
|
133
134
|
encrypt: options.encrypt,
|
|
135
|
+
strictArtifacts: options.strictArtifacts,
|
|
134
136
|
onStatus: (message) => {
|
|
135
137
|
spinner.text = message;
|
|
136
138
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,GAE1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1697,16 +1697,172 @@ import { Command as Command5 } from "commander";
|
|
|
1697
1697
|
import ora3 from "ora";
|
|
1698
1698
|
|
|
1699
1699
|
// src/lib/upload-workflow.ts
|
|
1700
|
-
import { createReadStream as createReadStream3, readFileSync as readFileSync5, readdirSync as
|
|
1700
|
+
import { createReadStream as createReadStream3, readFileSync as readFileSync5, readdirSync as readdirSync4, unlinkSync } from "node:fs";
|
|
1701
1701
|
import { stat as stat2 } from "node:fs/promises";
|
|
1702
1702
|
import { execFileSync } from "node:child_process";
|
|
1703
1703
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
1704
|
-
import { dirname as dirname7, join as
|
|
1704
|
+
import { dirname as dirname7, join as join6, posix as posix3, resolve as resolve6 } from "node:path";
|
|
1705
1705
|
import { tmpdir } from "node:os";
|
|
1706
1706
|
|
|
1707
|
+
// src/lib/artifact-preflight.ts
|
|
1708
|
+
import { lstatSync as lstatSync2, readdirSync as readdirSync3 } from "node:fs";
|
|
1709
|
+
import { join as join5, posix as posix2 } from "node:path";
|
|
1710
|
+
|
|
1711
|
+
// src/lib/zip.ts
|
|
1712
|
+
import { createWriteStream, existsSync as existsSync4, lstatSync, readdirSync as readdirSync2 } from "node:fs";
|
|
1713
|
+
import { stat, unlink as unlink2 } from "node:fs/promises";
|
|
1714
|
+
import { dirname as dirname6, join as join4, posix } from "node:path";
|
|
1715
|
+
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
1716
|
+
import yazl from "yazl";
|
|
1717
|
+
function validateBundleDirectory(directory) {
|
|
1718
|
+
if (!existsSync4(directory)) {
|
|
1719
|
+
throw new CliError(`Bundle directory does not exist: ${directory}`);
|
|
1720
|
+
}
|
|
1721
|
+
if (!lstatSync(directory).isDirectory()) {
|
|
1722
|
+
throw new CliError(`Not a directory: ${directory}`);
|
|
1723
|
+
}
|
|
1724
|
+
const indexPath = join4(directory, "index.html");
|
|
1725
|
+
if (!existsSync4(indexPath)) {
|
|
1726
|
+
throw new CliError(
|
|
1727
|
+
`Missing index.html in ${directory}. Expected a Capacitor web build output.`
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
if (!lstatSync(indexPath).isFile()) {
|
|
1731
|
+
throw new CliError(`index.html must be a regular file in ${directory}.`);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
function addDirectory(zipfile, sourceDirectory, relativePath) {
|
|
1735
|
+
const currentPath = join4(sourceDirectory, relativePath);
|
|
1736
|
+
const entries = readdirSync2(currentPath, { withFileTypes: true });
|
|
1737
|
+
for (const entry of entries) {
|
|
1738
|
+
const nextRelativePath = relativePath ? join4(relativePath, entry.name) : entry.name;
|
|
1739
|
+
const absolutePath = join4(sourceDirectory, nextRelativePath);
|
|
1740
|
+
const archiveName = nextRelativePath.split("\\").join(posix.sep);
|
|
1741
|
+
if (entry.isSymbolicLink()) {
|
|
1742
|
+
throw new CliError(
|
|
1743
|
+
[
|
|
1744
|
+
`Unsupported symlink in bundle output: ${archiveName}`,
|
|
1745
|
+
"Remove symlinks from the web build output before uploading."
|
|
1746
|
+
].join("\n")
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
if (entry.isDirectory()) {
|
|
1750
|
+
addDirectory(zipfile, sourceDirectory, nextRelativePath);
|
|
1751
|
+
continue;
|
|
1752
|
+
}
|
|
1753
|
+
if (entry.isFile()) {
|
|
1754
|
+
zipfile.addFile(absolutePath, archiveName, { compress: true });
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
async function createZip(sourceDirectory, destinationZipPath) {
|
|
1759
|
+
validateBundleDirectory(sourceDirectory);
|
|
1760
|
+
await mkdir2(dirname6(destinationZipPath), { recursive: true });
|
|
1761
|
+
return new Promise((resolve10, reject) => {
|
|
1762
|
+
const zipfile = new yazl.ZipFile();
|
|
1763
|
+
const output2 = createWriteStream(destinationZipPath);
|
|
1764
|
+
output2.on("close", async () => {
|
|
1765
|
+
try {
|
|
1766
|
+
const fileStats = await stat(destinationZipPath);
|
|
1767
|
+
resolve10({
|
|
1768
|
+
path: destinationZipPath,
|
|
1769
|
+
size: fileStats.size
|
|
1770
|
+
});
|
|
1771
|
+
} catch (error) {
|
|
1772
|
+
reject(error);
|
|
1773
|
+
}
|
|
1774
|
+
});
|
|
1775
|
+
output2.on("error", reject);
|
|
1776
|
+
addDirectory(zipfile, sourceDirectory, "");
|
|
1777
|
+
zipfile.outputStream.pipe(output2);
|
|
1778
|
+
zipfile.end();
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
async function removeFileIfExists(filePath) {
|
|
1782
|
+
try {
|
|
1783
|
+
await unlink2(filePath);
|
|
1784
|
+
} catch (error) {
|
|
1785
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1786
|
+
throw error;
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// src/lib/artifact-preflight.ts
|
|
1792
|
+
var MIB = 1024 * 1024;
|
|
1793
|
+
var MAX_UNPACKED_BYTES = 5e8;
|
|
1794
|
+
var INSTALLER = /\.(exe|msi|dmg|pkg|apk|ipa|appx|msix|deb|rpm)$/i;
|
|
1795
|
+
function inspectArtifacts(directory, strategy = "zip") {
|
|
1796
|
+
validateBundleDirectory(directory);
|
|
1797
|
+
const files = [];
|
|
1798
|
+
const maximumFiles = strategy === "deltas" ? 5e3 : 1e4;
|
|
1799
|
+
let totalBytes = 0;
|
|
1800
|
+
const walk = (relative5) => {
|
|
1801
|
+
for (const entry of readdirSync3(join5(directory, relative5), { withFileTypes: true })) {
|
|
1802
|
+
const path = relative5 ? posix2.join(relative5, entry.name) : entry.name;
|
|
1803
|
+
if (entry.isSymbolicLink()) {
|
|
1804
|
+
throw new CliError(`Unsupported symlink in bundle output: ${JSON.stringify(path)}`);
|
|
1805
|
+
}
|
|
1806
|
+
if (entry.isDirectory()) {
|
|
1807
|
+
walk(path);
|
|
1808
|
+
continue;
|
|
1809
|
+
}
|
|
1810
|
+
if (!entry.isFile()) {
|
|
1811
|
+
throw new CliError(`Unsupported non-file artifact: ${JSON.stringify(path)}`);
|
|
1812
|
+
}
|
|
1813
|
+
const bytes = lstatSync2(join5(directory, path)).size;
|
|
1814
|
+
totalBytes += bytes;
|
|
1815
|
+
files.push({ path, bytes });
|
|
1816
|
+
if (files.length > maximumFiles) {
|
|
1817
|
+
throw new CliError(`Bundle exceeds the ${strategy} limit of ${maximumFiles} files.`);
|
|
1818
|
+
}
|
|
1819
|
+
if (totalBytes > MAX_UNPACKED_BYTES) {
|
|
1820
|
+
throw new CliError(
|
|
1821
|
+
"Bundle exceeds the native extraction limit of 500,000,000 bytes. Reduce its assets before uploading."
|
|
1822
|
+
);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
};
|
|
1826
|
+
walk("");
|
|
1827
|
+
const largestFiles = [...files].sort((a, b) => b.bytes - a.bytes || a.path.localeCompare(b.path)).slice(0, 5);
|
|
1828
|
+
const nativeArtifacts = files.filter(
|
|
1829
|
+
(file) => INSTALLER.test(file.path) || file.path.split("/").some((part) => part.toLowerCase().endsWith(".app"))
|
|
1830
|
+
);
|
|
1831
|
+
const warnings = [];
|
|
1832
|
+
if (nativeArtifacts.length > 0) {
|
|
1833
|
+
const examples = nativeArtifacts.slice(0, 5).map((file) => `${JSON.stringify(file.path)} (${(file.bytes / MIB).toFixed(1)} MiB)`).join(", ");
|
|
1834
|
+
warnings.push(
|
|
1835
|
+
`Bundle contains ${nativeArtifacts.length} native installer/artifact file(s): ${examples}. Confirm these belong in the mobile web bundle; otherwise publish them separately.`
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
if (totalBytes >= 50 * MIB || largestFiles.some((file) => file.bytes >= 10 * MIB)) {
|
|
1839
|
+
const examples = largestFiles.map((file) => `${JSON.stringify(file.path)} (${(file.bytes / MIB).toFixed(1)} MiB)`).join(", ");
|
|
1840
|
+
warnings.push(
|
|
1841
|
+
`Large bundle: ${(totalBytes / MIB).toFixed(1)} MiB across ${files.length} files. Large downloads increase timeout, storage, and memory pressure. Largest files: ${examples}.`
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
return { fileCount: files.length, totalBytes, largestFiles, nativeArtifacts, warnings };
|
|
1845
|
+
}
|
|
1846
|
+
function preflightArtifacts(directory, options = {}) {
|
|
1847
|
+
const inspection = inspectArtifacts(directory, options.strategy);
|
|
1848
|
+
if (options.strict && inspection.warnings.length > 0) {
|
|
1849
|
+
throw new CliError(`Artifact preflight failed:
|
|
1850
|
+
${inspection.warnings.join("\n")}`);
|
|
1851
|
+
}
|
|
1852
|
+
for (const warning of inspection.warnings) (options.onWarning ?? console.warn)(warning);
|
|
1853
|
+
return inspection;
|
|
1854
|
+
}
|
|
1855
|
+
function validateEncryptedArchiveSize(zipBytes) {
|
|
1856
|
+
if (zipBytes + 16 > 128 * MIB) {
|
|
1857
|
+
throw new CliError(
|
|
1858
|
+
"Encrypted bundle exceeds the native 128 MiB limit (including its authentication tag). Reduce the bundle before uploading."
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1707
1863
|
// src/lib/crypto.ts
|
|
1708
1864
|
import { createCipheriv, createHash as createHash2, randomBytes } from "node:crypto";
|
|
1709
|
-
import { createReadStream, createWriteStream } from "node:fs";
|
|
1865
|
+
import { createReadStream, createWriteStream as createWriteStream2 } from "node:fs";
|
|
1710
1866
|
import { pipeline } from "node:stream/promises";
|
|
1711
1867
|
import { Transform } from "node:stream";
|
|
1712
1868
|
var ALGORITHM = "aes-256-gcm";
|
|
@@ -1750,7 +1906,7 @@ async function encryptFile(kek, inputPath, outputPath) {
|
|
|
1750
1906
|
callback(null, cipher.getAuthTag());
|
|
1751
1907
|
}
|
|
1752
1908
|
});
|
|
1753
|
-
await pipeline(createReadStream(inputPath), cipher, appendTag,
|
|
1909
|
+
await pipeline(createReadStream(inputPath), cipher, appendTag, createWriteStream2(outputPath));
|
|
1754
1910
|
const { wrapNonce, wrappedDek } = wrapDek(kek, dek);
|
|
1755
1911
|
return {
|
|
1756
1912
|
alg: ENCRYPTION_ALG,
|
|
@@ -1787,83 +1943,6 @@ async function hashFileWithMd5(filePath) {
|
|
|
1787
1943
|
});
|
|
1788
1944
|
}
|
|
1789
1945
|
|
|
1790
|
-
// src/lib/zip.ts
|
|
1791
|
-
import { createWriteStream as createWriteStream2, existsSync as existsSync4, lstatSync, readdirSync as readdirSync2 } from "node:fs";
|
|
1792
|
-
import { stat, unlink as unlink2 } from "node:fs/promises";
|
|
1793
|
-
import { dirname as dirname6, join as join4, posix } from "node:path";
|
|
1794
|
-
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
1795
|
-
import yazl from "yazl";
|
|
1796
|
-
function validateBundleDirectory(directory) {
|
|
1797
|
-
if (!existsSync4(directory)) {
|
|
1798
|
-
throw new CliError(`Bundle directory does not exist: ${directory}`);
|
|
1799
|
-
}
|
|
1800
|
-
if (!lstatSync(directory).isDirectory()) {
|
|
1801
|
-
throw new CliError(`Not a directory: ${directory}`);
|
|
1802
|
-
}
|
|
1803
|
-
const indexPath = join4(directory, "index.html");
|
|
1804
|
-
if (!existsSync4(indexPath)) {
|
|
1805
|
-
throw new CliError(
|
|
1806
|
-
`Missing index.html in ${directory}. Expected a Capacitor web build output.`
|
|
1807
|
-
);
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
function addDirectory(zipfile, sourceDirectory, relativePath) {
|
|
1811
|
-
const currentPath = join4(sourceDirectory, relativePath);
|
|
1812
|
-
const entries = readdirSync2(currentPath, { withFileTypes: true });
|
|
1813
|
-
for (const entry of entries) {
|
|
1814
|
-
const nextRelativePath = relativePath ? join4(relativePath, entry.name) : entry.name;
|
|
1815
|
-
const absolutePath = join4(sourceDirectory, nextRelativePath);
|
|
1816
|
-
const archiveName = nextRelativePath.split("\\").join(posix.sep);
|
|
1817
|
-
if (entry.isSymbolicLink()) {
|
|
1818
|
-
throw new CliError(
|
|
1819
|
-
[
|
|
1820
|
-
`Unsupported symlink in bundle output: ${archiveName}`,
|
|
1821
|
-
"Remove symlinks from the web build output before uploading."
|
|
1822
|
-
].join("\n")
|
|
1823
|
-
);
|
|
1824
|
-
}
|
|
1825
|
-
if (entry.isDirectory()) {
|
|
1826
|
-
addDirectory(zipfile, sourceDirectory, nextRelativePath);
|
|
1827
|
-
continue;
|
|
1828
|
-
}
|
|
1829
|
-
if (entry.isFile()) {
|
|
1830
|
-
zipfile.addFile(absolutePath, archiveName, { compress: true });
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
async function createZip(sourceDirectory, destinationZipPath) {
|
|
1835
|
-
validateBundleDirectory(sourceDirectory);
|
|
1836
|
-
await mkdir2(dirname6(destinationZipPath), { recursive: true });
|
|
1837
|
-
return new Promise((resolve10, reject) => {
|
|
1838
|
-
const zipfile = new yazl.ZipFile();
|
|
1839
|
-
const output2 = createWriteStream2(destinationZipPath);
|
|
1840
|
-
output2.on("close", async () => {
|
|
1841
|
-
try {
|
|
1842
|
-
const fileStats = await stat(destinationZipPath);
|
|
1843
|
-
resolve10({
|
|
1844
|
-
path: destinationZipPath,
|
|
1845
|
-
size: fileStats.size
|
|
1846
|
-
});
|
|
1847
|
-
} catch (error) {
|
|
1848
|
-
reject(error);
|
|
1849
|
-
}
|
|
1850
|
-
});
|
|
1851
|
-
output2.on("error", reject);
|
|
1852
|
-
addDirectory(zipfile, sourceDirectory, "");
|
|
1853
|
-
zipfile.outputStream.pipe(output2);
|
|
1854
|
-
zipfile.end();
|
|
1855
|
-
});
|
|
1856
|
-
}
|
|
1857
|
-
async function removeFileIfExists(filePath) {
|
|
1858
|
-
try {
|
|
1859
|
-
await unlink2(filePath);
|
|
1860
|
-
} catch (error) {
|
|
1861
|
-
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1862
|
-
throw error;
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
1946
|
// src/lib/upload-workflow.ts
|
|
1868
1947
|
var MAX_VERSION_LENGTH = 64;
|
|
1869
1948
|
var MAX_DELTA_FILES = 5e3;
|
|
@@ -1974,6 +2053,12 @@ function resolveEncryptionKey(encryptFlag) {
|
|
|
1974
2053
|
return parseEncryptionKey(raw);
|
|
1975
2054
|
}
|
|
1976
2055
|
async function runUploadWorkflow(options) {
|
|
2056
|
+
throwIfAborted(options.signal);
|
|
2057
|
+
preflightArtifacts(options.sourcePath, {
|
|
2058
|
+
strategy: options.strategy,
|
|
2059
|
+
strict: options.strictArtifacts,
|
|
2060
|
+
onWarning: options.onWarning
|
|
2061
|
+
});
|
|
1977
2062
|
if (options.strategy === "deltas") {
|
|
1978
2063
|
return runDeltaUploadWorkflow(options);
|
|
1979
2064
|
}
|
|
@@ -1999,7 +2084,7 @@ async function runUploadWorkflow(options) {
|
|
|
1999
2084
|
throwIfAborted(signal);
|
|
2000
2085
|
validateBundleDirectory(sourcePath);
|
|
2001
2086
|
const encryptionKey = resolveEncryptionKey(encrypt);
|
|
2002
|
-
const tempZipPath =
|
|
2087
|
+
const tempZipPath = join6(tmpdir(), `otakit-${version}-${randomUUID3()}.zip`);
|
|
2003
2088
|
const tempEncPath = `${tempZipPath}.enc`;
|
|
2004
2089
|
const cleanup = () => {
|
|
2005
2090
|
try {
|
|
@@ -2015,11 +2100,12 @@ async function runUploadWorkflow(options) {
|
|
|
2015
2100
|
if (manageProcessSignals) process.on("SIGINT", cleanup);
|
|
2016
2101
|
try {
|
|
2017
2102
|
onStatus?.("Creating zip archive...");
|
|
2018
|
-
await createZip(sourcePath, tempZipPath);
|
|
2103
|
+
const archive = await createZip(sourcePath, tempZipPath);
|
|
2019
2104
|
throwIfAborted(signal);
|
|
2020
2105
|
let uploadPath = tempZipPath;
|
|
2021
2106
|
let encryption;
|
|
2022
2107
|
if (encryptionKey) {
|
|
2108
|
+
validateEncryptedArchiveSize(archive.size);
|
|
2023
2109
|
onStatus?.("Encrypting bundle...");
|
|
2024
2110
|
encryption = await encryptFile(encryptionKey, tempZipPath, tempEncPath);
|
|
2025
2111
|
uploadPath = tempEncPath;
|
|
@@ -2081,12 +2167,12 @@ async function runUploadWorkflow(options) {
|
|
|
2081
2167
|
async function collectDeltaFiles(sourceDirectory) {
|
|
2082
2168
|
const files = [];
|
|
2083
2169
|
const walk = async (relativePath) => {
|
|
2084
|
-
const currentPath =
|
|
2085
|
-
const entries =
|
|
2170
|
+
const currentPath = join6(sourceDirectory, relativePath);
|
|
2171
|
+
const entries = readdirSync4(currentPath, { withFileTypes: true });
|
|
2086
2172
|
for (const entry of entries) {
|
|
2087
|
-
const nextRelativePath = relativePath ?
|
|
2088
|
-
const absolutePath =
|
|
2089
|
-
const posixPath = nextRelativePath.split("\\").join(
|
|
2173
|
+
const nextRelativePath = relativePath ? join6(relativePath, entry.name) : entry.name;
|
|
2174
|
+
const absolutePath = join6(sourceDirectory, nextRelativePath);
|
|
2175
|
+
const posixPath = nextRelativePath.split("\\").join(posix3.sep);
|
|
2090
2176
|
if (entry.isSymbolicLink()) {
|
|
2091
2177
|
throw new CliError(
|
|
2092
2178
|
[
|
|
@@ -2214,7 +2300,7 @@ async function runDeltaUploadWorkflow(options) {
|
|
|
2214
2300
|
throw new CliError(`Server requested unknown file hash: ${upload.sha256}`);
|
|
2215
2301
|
}
|
|
2216
2302
|
await uploadDeltaFileToPresignedUrl(
|
|
2217
|
-
|
|
2303
|
+
join6(sourcePath, source.path),
|
|
2218
2304
|
source.size,
|
|
2219
2305
|
source.md5,
|
|
2220
2306
|
upload.presignedUrl,
|
|
@@ -2287,7 +2373,7 @@ function normalizeBaseVersion(value) {
|
|
|
2287
2373
|
function readNearestPackageVersion(startPath) {
|
|
2288
2374
|
let currentDir = resolve6(startPath ?? process.cwd());
|
|
2289
2375
|
while (true) {
|
|
2290
|
-
const packageJsonPath =
|
|
2376
|
+
const packageJsonPath = join6(currentDir, "package.json");
|
|
2291
2377
|
try {
|
|
2292
2378
|
const raw = readFileSync5(packageJsonPath, "utf-8");
|
|
2293
2379
|
const parsed = JSON.parse(raw);
|
|
@@ -2386,7 +2472,10 @@ function resolveReleaseChannel(releaseOption) {
|
|
|
2386
2472
|
}
|
|
2387
2473
|
return normalizeChannel(releaseOption);
|
|
2388
2474
|
}
|
|
2389
|
-
var uploadCommand = new Command5("upload").description("Upload a new bundle").argument("[path]", "Path to the bundle directory").option("--app-id <id>", "App ID override").option("--server <url>", "Server URL override").option("--version <version>", "Version string (default: OTAKIT_VERSION, then auto-generated)").option("--strict-version", "Require explicit version (--version or OTAKIT_VERSION)").option(
|
|
2475
|
+
var uploadCommand = new Command5("upload").description("Upload a new bundle").argument("[path]", "Path to the bundle directory").option("--app-id <id>", "App ID override").option("--server <url>", "Server URL override").option("--version <version>", "Version string (default: OTAKIT_VERSION, then auto-generated)").option("--strict-version", "Require explicit version (--version or OTAKIT_VERSION)").option(
|
|
2476
|
+
"--strict-artifacts",
|
|
2477
|
+
"Fail before uploading on large bundles or native installer artifacts"
|
|
2478
|
+
).option("--release [channel]", "Release after upload (base channel if omitted)").option(
|
|
2390
2479
|
"--strategy <strategy>",
|
|
2391
2480
|
'Upload strategy: "zip" (single archive, default) or "deltas" (per-file objects)'
|
|
2392
2481
|
).option("--fail-on-incompatible", "Exit non-zero when native compatibility check fails").option("--ignore-compat", "Skip the native compatibility check").option("--package-json <path>", "package.json used for native dependency detection").option("--node-modules <path>", "node_modules used for native dependency detection").option(
|
|
@@ -2491,6 +2580,7 @@ var uploadCommand = new Command5("upload").description("Upload a new bundle").ar
|
|
|
2491
2580
|
autoRevertRatePercent,
|
|
2492
2581
|
autoRevertMinSample,
|
|
2493
2582
|
encrypt: options.encrypt,
|
|
2583
|
+
strictArtifacts: options.strictArtifacts,
|
|
2494
2584
|
onStatus: (message) => {
|
|
2495
2585
|
spinner.text = message;
|
|
2496
2586
|
}
|
|
@@ -3178,7 +3268,7 @@ var OTAKIT_TOOL_CATALOG = [
|
|
|
3178
3268
|
appId: resolvedAppIdSchema,
|
|
3179
3269
|
releaseId: releaseIdSchema.optional(),
|
|
3180
3270
|
bundleVersion: z2.string().trim().min(1).max(64).optional(),
|
|
3181
|
-
action: z2.enum(["downloaded", "applied", "download_error", "rollback"]).optional(),
|
|
3271
|
+
action: z2.enum(["downloaded", "applied", "download_error", "rollback", "check_error"]).optional(),
|
|
3182
3272
|
platform: z2.enum(["ios", "android"]).optional(),
|
|
3183
3273
|
channel: channelSchema.optional(),
|
|
3184
3274
|
runtimeVersion: runtimeVersionSchema.optional(),
|
|
@@ -3526,11 +3616,11 @@ import { Command as Command15 } from "commander";
|
|
|
3526
3616
|
|
|
3527
3617
|
// src/mcp/local-adapter.ts
|
|
3528
3618
|
import { realpathSync } from "node:fs";
|
|
3529
|
-
import { dirname as dirname9, join as
|
|
3619
|
+
import { dirname as dirname9, join as join8, relative as relative4, resolve as resolve8, sep as sep3 } from "node:path";
|
|
3530
3620
|
|
|
3531
3621
|
// src/lib/project-inspect.ts
|
|
3532
|
-
import { existsSync as existsSync5, readFileSync as readFileSync6, readdirSync as
|
|
3533
|
-
import { dirname as dirname8, join as
|
|
3622
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync } from "node:fs";
|
|
3623
|
+
import { dirname as dirname8, join as join7, relative as relative3, resolve as resolve7, sep as sep2 } from "node:path";
|
|
3534
3624
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"]);
|
|
3535
3625
|
var SKIPPED_DIRECTORIES2 = /* @__PURE__ */ new Set([
|
|
3536
3626
|
".git",
|
|
@@ -3555,12 +3645,12 @@ function findNotifyAppReady(root) {
|
|
|
3555
3645
|
if (!directory) break;
|
|
3556
3646
|
let entries;
|
|
3557
3647
|
try {
|
|
3558
|
-
entries =
|
|
3648
|
+
entries = readdirSync5(directory, { withFileTypes: true });
|
|
3559
3649
|
} catch {
|
|
3560
3650
|
continue;
|
|
3561
3651
|
}
|
|
3562
3652
|
for (const entry of entries) {
|
|
3563
|
-
const path =
|
|
3653
|
+
const path = join7(directory, entry.name);
|
|
3564
3654
|
if (entry.isDirectory() && !SKIPPED_DIRECTORIES2.has(entry.name)) {
|
|
3565
3655
|
queue.push(path);
|
|
3566
3656
|
continue;
|
|
@@ -3580,7 +3670,7 @@ function findNotifyAppReady(root) {
|
|
|
3580
3670
|
return null;
|
|
3581
3671
|
}
|
|
3582
3672
|
function pluginVersion(projectRoot) {
|
|
3583
|
-
const packageJsonPath =
|
|
3673
|
+
const packageJsonPath = join7(projectRoot, "package.json");
|
|
3584
3674
|
if (!existsSync5(packageJsonPath)) return null;
|
|
3585
3675
|
try {
|
|
3586
3676
|
const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
|
|
@@ -4164,12 +4254,12 @@ var LocalOtaKitToolAdapter = class {
|
|
|
4164
4254
|
}
|
|
4165
4255
|
nativePackages(projectRoot, input2) {
|
|
4166
4256
|
const packageJsonPath = optionalString(input2, "packageJsonPath") ? this.pathWithinProjectRoot(stringInput(input2, "packageJsonPath"), "packageJsonPath") : this.pathWithinProjectRoot(
|
|
4167
|
-
|
|
4257
|
+
join8(projectRoot, "package.json"),
|
|
4168
4258
|
"package.json",
|
|
4169
4259
|
"Point packageJsonPath at the package.json that declares this app\u2019s dependencies, for example in a workspace subdirectory."
|
|
4170
4260
|
);
|
|
4171
4261
|
const nodeModulesPath = optionalString(input2, "nodeModulesPath") ? this.pathWithinProjectRoot(stringInput(input2, "nodeModulesPath"), "nodeModulesPath") : this.pathWithinProjectRoot(
|
|
4172
|
-
|
|
4262
|
+
join8(dirname9(packageJsonPath), "node_modules"),
|
|
4173
4263
|
"node_modules",
|
|
4174
4264
|
"Install dependencies (npm install / pnpm install) so native packages can be detected, or pass nodeModulesPath if they live elsewhere."
|
|
4175
4265
|
);
|