@onexapis/cli 1.1.43 → 1.1.44
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/cli.js +172 -8
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +172 -8
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -4830,6 +4830,82 @@ async function whoamiCommand() {
|
|
|
4830
4830
|
|
|
4831
4831
|
// src/commands/publish.ts
|
|
4832
4832
|
init_logger();
|
|
4833
|
+
var MIME_MAP = {
|
|
4834
|
+
".png": "image/png",
|
|
4835
|
+
".jpg": "image/jpeg",
|
|
4836
|
+
".jpeg": "image/jpeg",
|
|
4837
|
+
".gif": "image/gif",
|
|
4838
|
+
".webp": "image/webp",
|
|
4839
|
+
".avif": "image/avif",
|
|
4840
|
+
".svg": "image/svg+xml",
|
|
4841
|
+
".ico": "image/x-icon",
|
|
4842
|
+
".bmp": "image/bmp",
|
|
4843
|
+
".woff": "font/woff",
|
|
4844
|
+
".woff2": "font/woff2",
|
|
4845
|
+
".ttf": "font/ttf",
|
|
4846
|
+
".otf": "font/otf",
|
|
4847
|
+
".eot": "application/vnd.ms-fontobject",
|
|
4848
|
+
".mp4": "video/mp4",
|
|
4849
|
+
".webm": "video/webm",
|
|
4850
|
+
".mov": "video/quicktime",
|
|
4851
|
+
".ogg": "video/ogg",
|
|
4852
|
+
".json": "application/json"
|
|
4853
|
+
};
|
|
4854
|
+
var HASH_LEN = 8;
|
|
4855
|
+
function mimeFor(filename) {
|
|
4856
|
+
const ext = path9.extname(filename).toLowerCase();
|
|
4857
|
+
return MIME_MAP[ext] || "application/octet-stream";
|
|
4858
|
+
}
|
|
4859
|
+
async function sha256Prefix(absPath, len) {
|
|
4860
|
+
const buf = await fs.readFile(absPath);
|
|
4861
|
+
return crypto.createHash("sha256").update(buf).digest("hex").slice(0, len);
|
|
4862
|
+
}
|
|
4863
|
+
function insertHashIntoName(relPath, hash) {
|
|
4864
|
+
const dir = path9.posix.dirname(relPath);
|
|
4865
|
+
const base = path9.posix.basename(relPath);
|
|
4866
|
+
const ext = path9.posix.extname(base);
|
|
4867
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
4868
|
+
const hashed = `${stem}-${hash}${ext}`;
|
|
4869
|
+
return dir === "." ? hashed : `${dir}/${hashed}`;
|
|
4870
|
+
}
|
|
4871
|
+
async function scanThemeAssets(distDir) {
|
|
4872
|
+
const assetsDir = path9.join(distDir, "theme-assets");
|
|
4873
|
+
if (!await fs.pathExists(assetsDir)) return [];
|
|
4874
|
+
const files = await glob("**/*", {
|
|
4875
|
+
cwd: assetsDir,
|
|
4876
|
+
nodir: true,
|
|
4877
|
+
dot: false
|
|
4878
|
+
});
|
|
4879
|
+
const results = [];
|
|
4880
|
+
for (const rel of files) {
|
|
4881
|
+
const absPath = path9.join(assetsDir, rel);
|
|
4882
|
+
const stat = await fs.stat(absPath);
|
|
4883
|
+
if (!stat.isFile()) continue;
|
|
4884
|
+
const originalPath = rel.split(path9.sep).join("/");
|
|
4885
|
+
const hash = await sha256Prefix(absPath, HASH_LEN);
|
|
4886
|
+
const hashedPath = insertHashIntoName(originalPath, hash);
|
|
4887
|
+
const contentType = mimeFor(rel);
|
|
4888
|
+
results.push({
|
|
4889
|
+
originalPath,
|
|
4890
|
+
hashedPath,
|
|
4891
|
+
hash,
|
|
4892
|
+
size: stat.size,
|
|
4893
|
+
contentType,
|
|
4894
|
+
absPath
|
|
4895
|
+
});
|
|
4896
|
+
}
|
|
4897
|
+
results.sort((a, b) => a.originalPath.localeCompare(b.originalPath));
|
|
4898
|
+
return results;
|
|
4899
|
+
}
|
|
4900
|
+
function buildAssetMap(entries) {
|
|
4901
|
+
const map = {};
|
|
4902
|
+
for (const e of entries) {
|
|
4903
|
+
map[e.originalPath] = e.hashedPath;
|
|
4904
|
+
}
|
|
4905
|
+
return map;
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4908
|
+
// src/commands/publish.ts
|
|
4833
4909
|
async function publishCommand(options) {
|
|
4834
4910
|
logger.header("OneX Theme Publish");
|
|
4835
4911
|
const tokens = await getValidTokens();
|
|
@@ -4964,37 +5040,123 @@ Or use the --bump flag:
|
|
|
4964
5040
|
logger.error(error instanceof Error ? error.message : "Build error");
|
|
4965
5041
|
process.exit(1);
|
|
4966
5042
|
}
|
|
4967
|
-
|
|
5043
|
+
const distDir = path9.join(themePath, "dist");
|
|
5044
|
+
let assetEntries = [];
|
|
5045
|
+
try {
|
|
5046
|
+
assetEntries = await scanThemeAssets(distDir);
|
|
5047
|
+
if (assetEntries.length > 0) {
|
|
5048
|
+
logger.info(`Found ${assetEntries.length} theme asset file(s)`);
|
|
5049
|
+
}
|
|
5050
|
+
} catch (error) {
|
|
5051
|
+
logger.error(
|
|
5052
|
+
`Asset scan failed: ${error instanceof Error ? error.message : "unknown"}`
|
|
5053
|
+
);
|
|
5054
|
+
process.exit(1);
|
|
5055
|
+
}
|
|
5056
|
+
try {
|
|
5057
|
+
const assetMap = buildAssetMap(assetEntries);
|
|
5058
|
+
const assetMapPath = path9.join(distDir, "asset-map.json");
|
|
5059
|
+
await fs.writeFile(assetMapPath, JSON.stringify(assetMap, null, 2));
|
|
5060
|
+
} catch (error) {
|
|
5061
|
+
logger.error(
|
|
5062
|
+
`Failed to write asset-map.json: ${error instanceof Error ? error.message : "unknown"}`
|
|
5063
|
+
);
|
|
5064
|
+
process.exit(1);
|
|
5065
|
+
}
|
|
5066
|
+
logger.startSpinner("Getting upload URLs...");
|
|
4968
5067
|
let bundleUploadUrl;
|
|
4969
5068
|
let sourceUploadUrl;
|
|
5069
|
+
let assetUploads = [];
|
|
5070
|
+
let alreadyUploaded = [];
|
|
4970
5071
|
try {
|
|
4971
5072
|
const pubResponse = await authenticatedFetch(
|
|
4972
5073
|
`${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`,
|
|
4973
5074
|
{
|
|
4974
5075
|
method: "POST",
|
|
4975
|
-
body: JSON.stringify({
|
|
5076
|
+
body: JSON.stringify({
|
|
5077
|
+
version: version2,
|
|
5078
|
+
assets: assetEntries.map((a) => ({
|
|
5079
|
+
path: a.hashedPath,
|
|
5080
|
+
hash: a.hash,
|
|
5081
|
+
size: a.size,
|
|
5082
|
+
content_type: a.contentType
|
|
5083
|
+
}))
|
|
5084
|
+
})
|
|
4976
5085
|
}
|
|
4977
5086
|
);
|
|
4978
5087
|
const pubData = await pubResponse.json();
|
|
4979
5088
|
const pubBody = pubData.statusCode ? pubData.body : pubData;
|
|
4980
5089
|
if (!pubResponse.ok || !pubBody.bundleUploadUrl) {
|
|
4981
|
-
logger.stopSpinner(false, "Failed to get upload
|
|
5090
|
+
logger.stopSpinner(false, "Failed to get upload URLs");
|
|
4982
5091
|
logger.error(pubBody.error || "Server error");
|
|
4983
5092
|
process.exit(1);
|
|
4984
5093
|
}
|
|
4985
5094
|
bundleUploadUrl = pubBody.bundleUploadUrl;
|
|
4986
5095
|
sourceUploadUrl = pubBody.sourceUploadUrl;
|
|
4987
|
-
|
|
5096
|
+
assetUploads = pubBody.assetUploads || [];
|
|
5097
|
+
alreadyUploaded = pubBody.alreadyUploaded || [];
|
|
5098
|
+
logger.stopSpinner(
|
|
5099
|
+
true,
|
|
5100
|
+
`Upload URLs obtained (${assetUploads.length} new, ${alreadyUploaded.length} reused)`
|
|
5101
|
+
);
|
|
4988
5102
|
} catch (error) {
|
|
4989
5103
|
logger.stopSpinner(false, "Failed");
|
|
4990
5104
|
logger.error(error instanceof Error ? error.message : "Connection failed");
|
|
4991
5105
|
process.exit(1);
|
|
4992
5106
|
}
|
|
5107
|
+
if (assetUploads.length > 0) {
|
|
5108
|
+
logger.startSpinner(`Uploading ${assetUploads.length} asset(s) to S3...`);
|
|
5109
|
+
const CONCURRENCY = 8;
|
|
5110
|
+
const byHashedPath = new Map(assetEntries.map((a) => [a.hashedPath, a]));
|
|
5111
|
+
const queue = [...assetUploads];
|
|
5112
|
+
let uploaded = 0;
|
|
5113
|
+
let failed = 0;
|
|
5114
|
+
async function worker() {
|
|
5115
|
+
while (queue.length > 0) {
|
|
5116
|
+
const item = queue.shift();
|
|
5117
|
+
if (!item) break;
|
|
5118
|
+
const entry = byHashedPath.get(item.path);
|
|
5119
|
+
if (!entry) {
|
|
5120
|
+
failed++;
|
|
5121
|
+
logger.error(` \u2717 ${item.path}: no local file found`);
|
|
5122
|
+
continue;
|
|
5123
|
+
}
|
|
5124
|
+
try {
|
|
5125
|
+
const buf = await fs.promises.readFile(entry.absPath);
|
|
5126
|
+
const res = await fetch(item.upload_url, {
|
|
5127
|
+
method: "PUT",
|
|
5128
|
+
headers: {
|
|
5129
|
+
"Content-Type": entry.contentType,
|
|
5130
|
+
"x-amz-acl": "public-read"
|
|
5131
|
+
},
|
|
5132
|
+
body: buf
|
|
5133
|
+
});
|
|
5134
|
+
if (!res.ok) {
|
|
5135
|
+
throw new Error(`HTTP ${res.status}`);
|
|
5136
|
+
}
|
|
5137
|
+
uploaded++;
|
|
5138
|
+
} catch (e) {
|
|
5139
|
+
failed++;
|
|
5140
|
+
logger.error(
|
|
5141
|
+
` \u2717 ${item.path}: ${e instanceof Error ? e.message : "failed"}`
|
|
5142
|
+
);
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
await Promise.all(
|
|
5147
|
+
Array.from(
|
|
5148
|
+
{ length: Math.min(CONCURRENCY, assetUploads.length) },
|
|
5149
|
+
() => worker()
|
|
5150
|
+
)
|
|
5151
|
+
);
|
|
5152
|
+
if (failed > 0) {
|
|
5153
|
+
logger.stopSpinner(false, `${failed} asset(s) failed`);
|
|
5154
|
+
process.exit(1);
|
|
5155
|
+
}
|
|
5156
|
+
logger.stopSpinner(true, `Uploaded ${uploaded} asset(s)`);
|
|
5157
|
+
}
|
|
4993
5158
|
logger.startSpinner("Uploading bundle...");
|
|
4994
5159
|
try {
|
|
4995
|
-
const archiver3 = await import('archiver');
|
|
4996
|
-
const { createWriteStream } = await import('fs');
|
|
4997
|
-
const distDir = path9.join(themePath, "dist");
|
|
4998
5160
|
if (!fs.existsSync(distDir)) {
|
|
4999
5161
|
logger.stopSpinner(false, "No dist/ directory");
|
|
5000
5162
|
logger.error("Build the theme first: onexthm build");
|
|
@@ -5005,7 +5167,9 @@ Or use the --bump flag:
|
|
|
5005
5167
|
"bundle.zip",
|
|
5006
5168
|
"source.zip",
|
|
5007
5169
|
"preview-runtime.js",
|
|
5008
|
-
"preview-runtime.js.map"
|
|
5170
|
+
"preview-runtime.js.map",
|
|
5171
|
+
"theme-assets",
|
|
5172
|
+
"theme-assets/**"
|
|
5009
5173
|
]);
|
|
5010
5174
|
const bundleBuffer = fs.readFileSync(bundleZipPath);
|
|
5011
5175
|
const bundleRes = await fetch(bundleUploadUrl, {
|