@onexapis/cli 1.1.42 → 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 +194 -15
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +194 -15
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -749,6 +749,14 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
749
749
|
} catch {
|
|
750
750
|
}
|
|
751
751
|
await contentHashEntry(outputDir);
|
|
752
|
+
const themeAssetsDir = path9.join(themePath, "assets");
|
|
753
|
+
const distThemeAssets = path9.join(outputDir, "theme-assets");
|
|
754
|
+
try {
|
|
755
|
+
await fs8.access(themeAssetsDir);
|
|
756
|
+
await fs8.cp(themeAssetsDir, distThemeAssets, { recursive: true });
|
|
757
|
+
logger.info("Copied static assets to dist/theme-assets/");
|
|
758
|
+
} catch {
|
|
759
|
+
}
|
|
752
760
|
await generateManifest(themeName, themePath, outputDir);
|
|
753
761
|
await generateThemeData(themePath, outputDir, themeName);
|
|
754
762
|
await generateThemeCSS(themePath, outputDir);
|
|
@@ -4295,20 +4303,27 @@ function createDevServer(options) {
|
|
|
4295
4303
|
if (pathname.startsWith("/assets/")) {
|
|
4296
4304
|
const subpath = pathname.replace(/^\/assets\//, "");
|
|
4297
4305
|
const segments = subpath.split("/");
|
|
4306
|
+
const assetsBase = path9.join(options.themePath, "assets");
|
|
4298
4307
|
let assetPath;
|
|
4299
4308
|
if (segments[0] === options.themeName || segments[0] === options.themeName.replace(/^my-/, "")) {
|
|
4300
|
-
assetPath = path9.join(
|
|
4301
|
-
options.themePath,
|
|
4302
|
-
"assets",
|
|
4303
|
-
segments.slice(1).join("/")
|
|
4304
|
-
);
|
|
4309
|
+
assetPath = path9.join(assetsBase, segments.slice(1).join("/"));
|
|
4305
4310
|
} else {
|
|
4306
|
-
assetPath = path9.join(
|
|
4311
|
+
assetPath = path9.join(assetsBase, subpath);
|
|
4307
4312
|
}
|
|
4308
|
-
if (assetPath.startsWith(
|
|
4313
|
+
if (assetPath.startsWith(assetsBase) && fs3.existsSync(assetPath)) {
|
|
4309
4314
|
serveFile(res, assetPath);
|
|
4310
4315
|
return;
|
|
4311
4316
|
}
|
|
4317
|
+
if (segments.length > 1) {
|
|
4318
|
+
const fallbackPath = path9.join(
|
|
4319
|
+
assetsBase,
|
|
4320
|
+
segments.slice(1).join("/")
|
|
4321
|
+
);
|
|
4322
|
+
if (fallbackPath.startsWith(assetsBase) && fs3.existsSync(fallbackPath)) {
|
|
4323
|
+
serveFile(res, fallbackPath);
|
|
4324
|
+
return;
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4312
4327
|
}
|
|
4313
4328
|
const filePath = path9.join(options.distDir, pathname);
|
|
4314
4329
|
if (!filePath.startsWith(options.distDir)) {
|
|
@@ -4815,6 +4830,82 @@ async function whoamiCommand() {
|
|
|
4815
4830
|
|
|
4816
4831
|
// src/commands/publish.ts
|
|
4817
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
|
|
4818
4909
|
async function publishCommand(options) {
|
|
4819
4910
|
logger.header("OneX Theme Publish");
|
|
4820
4911
|
const tokens = await getValidTokens();
|
|
@@ -4949,37 +5040,123 @@ Or use the --bump flag:
|
|
|
4949
5040
|
logger.error(error instanceof Error ? error.message : "Build error");
|
|
4950
5041
|
process.exit(1);
|
|
4951
5042
|
}
|
|
4952
|
-
|
|
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...");
|
|
4953
5067
|
let bundleUploadUrl;
|
|
4954
5068
|
let sourceUploadUrl;
|
|
5069
|
+
let assetUploads = [];
|
|
5070
|
+
let alreadyUploaded = [];
|
|
4955
5071
|
try {
|
|
4956
5072
|
const pubResponse = await authenticatedFetch(
|
|
4957
5073
|
`${apiUrl}/website-api/themes/${encodeURIComponent(themeId)}/versions`,
|
|
4958
5074
|
{
|
|
4959
5075
|
method: "POST",
|
|
4960
|
-
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
|
+
})
|
|
4961
5085
|
}
|
|
4962
5086
|
);
|
|
4963
5087
|
const pubData = await pubResponse.json();
|
|
4964
5088
|
const pubBody = pubData.statusCode ? pubData.body : pubData;
|
|
4965
5089
|
if (!pubResponse.ok || !pubBody.bundleUploadUrl) {
|
|
4966
|
-
logger.stopSpinner(false, "Failed to get upload
|
|
5090
|
+
logger.stopSpinner(false, "Failed to get upload URLs");
|
|
4967
5091
|
logger.error(pubBody.error || "Server error");
|
|
4968
5092
|
process.exit(1);
|
|
4969
5093
|
}
|
|
4970
5094
|
bundleUploadUrl = pubBody.bundleUploadUrl;
|
|
4971
5095
|
sourceUploadUrl = pubBody.sourceUploadUrl;
|
|
4972
|
-
|
|
5096
|
+
assetUploads = pubBody.assetUploads || [];
|
|
5097
|
+
alreadyUploaded = pubBody.alreadyUploaded || [];
|
|
5098
|
+
logger.stopSpinner(
|
|
5099
|
+
true,
|
|
5100
|
+
`Upload URLs obtained (${assetUploads.length} new, ${alreadyUploaded.length} reused)`
|
|
5101
|
+
);
|
|
4973
5102
|
} catch (error) {
|
|
4974
5103
|
logger.stopSpinner(false, "Failed");
|
|
4975
5104
|
logger.error(error instanceof Error ? error.message : "Connection failed");
|
|
4976
5105
|
process.exit(1);
|
|
4977
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
|
+
}
|
|
4978
5158
|
logger.startSpinner("Uploading bundle...");
|
|
4979
5159
|
try {
|
|
4980
|
-
const archiver3 = await import('archiver');
|
|
4981
|
-
const { createWriteStream } = await import('fs');
|
|
4982
|
-
const distDir = path9.join(themePath, "dist");
|
|
4983
5160
|
if (!fs.existsSync(distDir)) {
|
|
4984
5161
|
logger.stopSpinner(false, "No dist/ directory");
|
|
4985
5162
|
logger.error("Build the theme first: onexthm build");
|
|
@@ -4990,7 +5167,9 @@ Or use the --bump flag:
|
|
|
4990
5167
|
"bundle.zip",
|
|
4991
5168
|
"source.zip",
|
|
4992
5169
|
"preview-runtime.js",
|
|
4993
|
-
"preview-runtime.js.map"
|
|
5170
|
+
"preview-runtime.js.map",
|
|
5171
|
+
"theme-assets",
|
|
5172
|
+
"theme-assets/**"
|
|
4994
5173
|
]);
|
|
4995
5174
|
const bundleBuffer = fs.readFileSync(bundleZipPath);
|
|
4996
5175
|
const bundleRes = await fetch(bundleUploadUrl, {
|