@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.js
CHANGED
|
@@ -4873,6 +4873,82 @@ async function whoamiCommand() {
|
|
|
4873
4873
|
|
|
4874
4874
|
// src/commands/publish.ts
|
|
4875
4875
|
init_logger();
|
|
4876
|
+
var MIME_MAP = {
|
|
4877
|
+
".png": "image/png",
|
|
4878
|
+
".jpg": "image/jpeg",
|
|
4879
|
+
".jpeg": "image/jpeg",
|
|
4880
|
+
".gif": "image/gif",
|
|
4881
|
+
".webp": "image/webp",
|
|
4882
|
+
".avif": "image/avif",
|
|
4883
|
+
".svg": "image/svg+xml",
|
|
4884
|
+
".ico": "image/x-icon",
|
|
4885
|
+
".bmp": "image/bmp",
|
|
4886
|
+
".woff": "font/woff",
|
|
4887
|
+
".woff2": "font/woff2",
|
|
4888
|
+
".ttf": "font/ttf",
|
|
4889
|
+
".otf": "font/otf",
|
|
4890
|
+
".eot": "application/vnd.ms-fontobject",
|
|
4891
|
+
".mp4": "video/mp4",
|
|
4892
|
+
".webm": "video/webm",
|
|
4893
|
+
".mov": "video/quicktime",
|
|
4894
|
+
".ogg": "video/ogg",
|
|
4895
|
+
".json": "application/json"
|
|
4896
|
+
};
|
|
4897
|
+
var HASH_LEN = 8;
|
|
4898
|
+
function mimeFor(filename) {
|
|
4899
|
+
const ext = path9__default.default.extname(filename).toLowerCase();
|
|
4900
|
+
return MIME_MAP[ext] || "application/octet-stream";
|
|
4901
|
+
}
|
|
4902
|
+
async function sha256Prefix(absPath, len) {
|
|
4903
|
+
const buf = await fs__default.default.readFile(absPath);
|
|
4904
|
+
return crypto__default.default.createHash("sha256").update(buf).digest("hex").slice(0, len);
|
|
4905
|
+
}
|
|
4906
|
+
function insertHashIntoName(relPath, hash) {
|
|
4907
|
+
const dir = path9__default.default.posix.dirname(relPath);
|
|
4908
|
+
const base = path9__default.default.posix.basename(relPath);
|
|
4909
|
+
const ext = path9__default.default.posix.extname(base);
|
|
4910
|
+
const stem = ext ? base.slice(0, -ext.length) : base;
|
|
4911
|
+
const hashed = `${stem}-${hash}${ext}`;
|
|
4912
|
+
return dir === "." ? hashed : `${dir}/${hashed}`;
|
|
4913
|
+
}
|
|
4914
|
+
async function scanThemeAssets(distDir) {
|
|
4915
|
+
const assetsDir = path9__default.default.join(distDir, "theme-assets");
|
|
4916
|
+
if (!await fs__default.default.pathExists(assetsDir)) return [];
|
|
4917
|
+
const files = await glob.glob("**/*", {
|
|
4918
|
+
cwd: assetsDir,
|
|
4919
|
+
nodir: true,
|
|
4920
|
+
dot: false
|
|
4921
|
+
});
|
|
4922
|
+
const results = [];
|
|
4923
|
+
for (const rel of files) {
|
|
4924
|
+
const absPath = path9__default.default.join(assetsDir, rel);
|
|
4925
|
+
const stat = await fs__default.default.stat(absPath);
|
|
4926
|
+
if (!stat.isFile()) continue;
|
|
4927
|
+
const originalPath = rel.split(path9__default.default.sep).join("/");
|
|
4928
|
+
const hash = await sha256Prefix(absPath, HASH_LEN);
|
|
4929
|
+
const hashedPath = insertHashIntoName(originalPath, hash);
|
|
4930
|
+
const contentType = mimeFor(rel);
|
|
4931
|
+
results.push({
|
|
4932
|
+
originalPath,
|
|
4933
|
+
hashedPath,
|
|
4934
|
+
hash,
|
|
4935
|
+
size: stat.size,
|
|
4936
|
+
contentType,
|
|
4937
|
+
absPath
|
|
4938
|
+
});
|
|
4939
|
+
}
|
|
4940
|
+
results.sort((a, b) => a.originalPath.localeCompare(b.originalPath));
|
|
4941
|
+
return results;
|
|
4942
|
+
}
|
|
4943
|
+
function buildAssetMap(entries) {
|
|
4944
|
+
const map = {};
|
|
4945
|
+
for (const e of entries) {
|
|
4946
|
+
map[e.originalPath] = e.hashedPath;
|
|
4947
|
+
}
|
|
4948
|
+
return map;
|
|
4949
|
+
}
|
|
4950
|
+
|
|
4951
|
+
// src/commands/publish.ts
|
|
4876
4952
|
async function publishCommand(options) {
|
|
4877
4953
|
logger.header("OneX Theme Publish");
|
|
4878
4954
|
const tokens = await getValidTokens();
|
|
@@ -5007,37 +5083,123 @@ Or use the --bump flag:
|
|
|
5007
5083
|
logger.error(error instanceof Error ? error.message : "Build error");
|
|
5008
5084
|
process.exit(1);
|
|
5009
5085
|
}
|
|
5010
|
-
|
|
5086
|
+
const distDir = path9__default.default.join(themePath, "dist");
|
|
5087
|
+
let assetEntries = [];
|
|
5088
|
+
try {
|
|
5089
|
+
assetEntries = await scanThemeAssets(distDir);
|
|
5090
|
+
if (assetEntries.length > 0) {
|
|
5091
|
+
logger.info(`Found ${assetEntries.length} theme asset file(s)`);
|
|
5092
|
+
}
|
|
5093
|
+
} catch (error) {
|
|
5094
|
+
logger.error(
|
|
5095
|
+
`Asset scan failed: ${error instanceof Error ? error.message : "unknown"}`
|
|
5096
|
+
);
|
|
5097
|
+
process.exit(1);
|
|
5098
|
+
}
|
|
5099
|
+
try {
|
|
5100
|
+
const assetMap = buildAssetMap(assetEntries);
|
|
5101
|
+
const assetMapPath = path9__default.default.join(distDir, "asset-map.json");
|
|
5102
|
+
await fs__default.default.writeFile(assetMapPath, JSON.stringify(assetMap, null, 2));
|
|
5103
|
+
} catch (error) {
|
|
5104
|
+
logger.error(
|
|
5105
|
+
`Failed to write asset-map.json: ${error instanceof Error ? error.message : "unknown"}`
|
|
5106
|
+
);
|
|
5107
|
+
process.exit(1);
|
|
5108
|
+
}
|
|
5109
|
+
logger.startSpinner("Getting upload URLs...");
|
|
5011
5110
|
let bundleUploadUrl;
|
|
5012
5111
|
let sourceUploadUrl;
|
|
5112
|
+
let assetUploads = [];
|
|
5113
|
+
let alreadyUploaded = [];
|
|
5013
5114
|
try {
|
|
5014
5115
|
const pubResponse = await authenticatedFetch(
|
|
5015
5116
|
`${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`,
|
|
5016
5117
|
{
|
|
5017
5118
|
method: "POST",
|
|
5018
|
-
body: JSON.stringify({
|
|
5119
|
+
body: JSON.stringify({
|
|
5120
|
+
version: version2,
|
|
5121
|
+
assets: assetEntries.map((a) => ({
|
|
5122
|
+
path: a.hashedPath,
|
|
5123
|
+
hash: a.hash,
|
|
5124
|
+
size: a.size,
|
|
5125
|
+
content_type: a.contentType
|
|
5126
|
+
}))
|
|
5127
|
+
})
|
|
5019
5128
|
}
|
|
5020
5129
|
);
|
|
5021
5130
|
const pubData = await pubResponse.json();
|
|
5022
5131
|
const pubBody = pubData.statusCode ? pubData.body : pubData;
|
|
5023
5132
|
if (!pubResponse.ok || !pubBody.bundleUploadUrl) {
|
|
5024
|
-
logger.stopSpinner(false, "Failed to get upload
|
|
5133
|
+
logger.stopSpinner(false, "Failed to get upload URLs");
|
|
5025
5134
|
logger.error(pubBody.error || "Server error");
|
|
5026
5135
|
process.exit(1);
|
|
5027
5136
|
}
|
|
5028
5137
|
bundleUploadUrl = pubBody.bundleUploadUrl;
|
|
5029
5138
|
sourceUploadUrl = pubBody.sourceUploadUrl;
|
|
5030
|
-
|
|
5139
|
+
assetUploads = pubBody.assetUploads || [];
|
|
5140
|
+
alreadyUploaded = pubBody.alreadyUploaded || [];
|
|
5141
|
+
logger.stopSpinner(
|
|
5142
|
+
true,
|
|
5143
|
+
`Upload URLs obtained (${assetUploads.length} new, ${alreadyUploaded.length} reused)`
|
|
5144
|
+
);
|
|
5031
5145
|
} catch (error) {
|
|
5032
5146
|
logger.stopSpinner(false, "Failed");
|
|
5033
5147
|
logger.error(error instanceof Error ? error.message : "Connection failed");
|
|
5034
5148
|
process.exit(1);
|
|
5035
5149
|
}
|
|
5150
|
+
if (assetUploads.length > 0) {
|
|
5151
|
+
logger.startSpinner(`Uploading ${assetUploads.length} asset(s) to S3...`);
|
|
5152
|
+
const CONCURRENCY = 8;
|
|
5153
|
+
const byHashedPath = new Map(assetEntries.map((a) => [a.hashedPath, a]));
|
|
5154
|
+
const queue = [...assetUploads];
|
|
5155
|
+
let uploaded = 0;
|
|
5156
|
+
let failed = 0;
|
|
5157
|
+
async function worker() {
|
|
5158
|
+
while (queue.length > 0) {
|
|
5159
|
+
const item = queue.shift();
|
|
5160
|
+
if (!item) break;
|
|
5161
|
+
const entry = byHashedPath.get(item.path);
|
|
5162
|
+
if (!entry) {
|
|
5163
|
+
failed++;
|
|
5164
|
+
logger.error(` \u2717 ${item.path}: no local file found`);
|
|
5165
|
+
continue;
|
|
5166
|
+
}
|
|
5167
|
+
try {
|
|
5168
|
+
const buf = await fs__default.default.promises.readFile(entry.absPath);
|
|
5169
|
+
const res = await fetch(item.upload_url, {
|
|
5170
|
+
method: "PUT",
|
|
5171
|
+
headers: {
|
|
5172
|
+
"Content-Type": entry.contentType,
|
|
5173
|
+
"x-amz-acl": "public-read"
|
|
5174
|
+
},
|
|
5175
|
+
body: buf
|
|
5176
|
+
});
|
|
5177
|
+
if (!res.ok) {
|
|
5178
|
+
throw new Error(`HTTP ${res.status}`);
|
|
5179
|
+
}
|
|
5180
|
+
uploaded++;
|
|
5181
|
+
} catch (e) {
|
|
5182
|
+
failed++;
|
|
5183
|
+
logger.error(
|
|
5184
|
+
` \u2717 ${item.path}: ${e instanceof Error ? e.message : "failed"}`
|
|
5185
|
+
);
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
await Promise.all(
|
|
5190
|
+
Array.from(
|
|
5191
|
+
{ length: Math.min(CONCURRENCY, assetUploads.length) },
|
|
5192
|
+
() => worker()
|
|
5193
|
+
)
|
|
5194
|
+
);
|
|
5195
|
+
if (failed > 0) {
|
|
5196
|
+
logger.stopSpinner(false, `${failed} asset(s) failed`);
|
|
5197
|
+
process.exit(1);
|
|
5198
|
+
}
|
|
5199
|
+
logger.stopSpinner(true, `Uploaded ${uploaded} asset(s)`);
|
|
5200
|
+
}
|
|
5036
5201
|
logger.startSpinner("Uploading bundle...");
|
|
5037
5202
|
try {
|
|
5038
|
-
const archiver3 = await import('archiver');
|
|
5039
|
-
const { createWriteStream } = await import('fs');
|
|
5040
|
-
const distDir = path9__default.default.join(themePath, "dist");
|
|
5041
5203
|
if (!fs__default.default.existsSync(distDir)) {
|
|
5042
5204
|
logger.stopSpinner(false, "No dist/ directory");
|
|
5043
5205
|
logger.error("Build the theme first: onexthm build");
|
|
@@ -5048,7 +5210,9 @@ Or use the --bump flag:
|
|
|
5048
5210
|
"bundle.zip",
|
|
5049
5211
|
"source.zip",
|
|
5050
5212
|
"preview-runtime.js",
|
|
5051
|
-
"preview-runtime.js.map"
|
|
5213
|
+
"preview-runtime.js.map",
|
|
5214
|
+
"theme-assets",
|
|
5215
|
+
"theme-assets/**"
|
|
5052
5216
|
]);
|
|
5053
5217
|
const bundleBuffer = fs__default.default.readFileSync(bundleZipPath);
|
|
5054
5218
|
const bundleRes = await fetch(bundleUploadUrl, {
|