@onexapis/cli 1.0.0 → 1.0.1
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/README.md +197 -214
- package/dist/cli.js +423 -183
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +422 -184
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +25 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +418 -184
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +416 -186
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,9 @@ var ora = require('ora');
|
|
|
9
9
|
var fs = require('fs-extra');
|
|
10
10
|
var ejs = require('ejs');
|
|
11
11
|
var clientS3 = require('@aws-sdk/client-s3');
|
|
12
|
-
var
|
|
12
|
+
var os = require('os');
|
|
13
|
+
var archiver = require('archiver');
|
|
14
|
+
var AdmZip = require('adm-zip');
|
|
13
15
|
|
|
14
16
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
17
|
|
|
@@ -20,6 +22,9 @@ var chalk4__default = /*#__PURE__*/_interopDefault(chalk4);
|
|
|
20
22
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
21
23
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
22
24
|
var ejs__default = /*#__PURE__*/_interopDefault(ejs);
|
|
25
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
26
|
+
var archiver__default = /*#__PURE__*/_interopDefault(archiver);
|
|
27
|
+
var AdmZip__default = /*#__PURE__*/_interopDefault(AdmZip);
|
|
23
28
|
|
|
24
29
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
25
30
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
@@ -99,8 +104,8 @@ function validateThemeName(name) {
|
|
|
99
104
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
100
105
|
}
|
|
101
106
|
function pathExists(filePath) {
|
|
102
|
-
const
|
|
103
|
-
return
|
|
107
|
+
const fs8 = __require("fs-extra");
|
|
108
|
+
return fs8.existsSync(filePath);
|
|
104
109
|
}
|
|
105
110
|
function validateCategory(category) {
|
|
106
111
|
const validCategories = [
|
|
@@ -217,18 +222,19 @@ function getProjectRoot() {
|
|
|
217
222
|
return process.cwd();
|
|
218
223
|
}
|
|
219
224
|
function getThemesDir() {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return
|
|
225
|
+
const root = getProjectRoot();
|
|
226
|
+
const themesDir = path__default.default.join(root, "themes");
|
|
227
|
+
if (fs__default.default.existsSync(themesDir)) {
|
|
228
|
+
return themesDir;
|
|
224
229
|
}
|
|
230
|
+
return path__default.default.join(root, "src/themes");
|
|
225
231
|
}
|
|
226
232
|
function getFeaturesDir() {
|
|
227
233
|
return path__default.default.join(getProjectRoot(), "src/features");
|
|
228
234
|
}
|
|
229
235
|
function isOneXProject() {
|
|
230
236
|
const root = getProjectRoot();
|
|
231
|
-
return fs__default.default.existsSync(path__default.default.join(root, "
|
|
237
|
+
return fs__default.default.existsSync(path__default.default.join(root, "themes")) || fs__default.default.existsSync(path__default.default.join(root, "src/themes"));
|
|
232
238
|
}
|
|
233
239
|
function ensureOneXProject() {
|
|
234
240
|
if (!isOneXProject()) {
|
|
@@ -245,12 +251,12 @@ function listThemes() {
|
|
|
245
251
|
}
|
|
246
252
|
return fs__default.default.readdirSync(themesDir).filter((name) => {
|
|
247
253
|
const themePath = path__default.default.join(themesDir, name);
|
|
248
|
-
return fs__default.default.statSync(themePath).isDirectory() && fs__default.default.existsSync(path__default.default.join(themePath, "manifest.ts"));
|
|
254
|
+
return fs__default.default.statSync(themePath).isDirectory() && (fs__default.default.existsSync(path__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path__default.default.join(themePath, "manifest.ts")));
|
|
249
255
|
});
|
|
250
256
|
}
|
|
251
257
|
function themeExists(themeName) {
|
|
252
258
|
const themePath = path__default.default.join(getThemesDir(), themeName);
|
|
253
|
-
return fs__default.default.existsSync(themePath) && fs__default.default.existsSync(path__default.default.join(themePath, "manifest.ts"));
|
|
259
|
+
return fs__default.default.existsSync(themePath) && (fs__default.default.existsSync(path__default.default.join(themePath, "theme.config.ts")) || fs__default.default.existsSync(path__default.default.join(themePath, "bundle-entry.ts")) || fs__default.default.existsSync(path__default.default.join(themePath, "manifest.ts")));
|
|
254
260
|
}
|
|
255
261
|
function detectPackageManager() {
|
|
256
262
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -444,7 +450,9 @@ Add your theme-specific blocks here.
|
|
|
444
450
|
logger.newLine();
|
|
445
451
|
logger.section("Theme structure:");
|
|
446
452
|
logger.log(" src/manifest.ts - Theme manifest and exports");
|
|
447
|
-
logger.log(
|
|
453
|
+
logger.log(
|
|
454
|
+
" src/config.ts - Design tokens (colors, typography, etc.)"
|
|
455
|
+
);
|
|
448
456
|
logger.log(" src/layout.ts - Header and footer configuration");
|
|
449
457
|
logger.log(" src/sections/ - Custom sections for your theme");
|
|
450
458
|
logger.log(" src/blocks/ - Reusable blocks");
|
|
@@ -1447,8 +1455,16 @@ async function listThemesInfo() {
|
|
|
1447
1455
|
}
|
|
1448
1456
|
logger.log("");
|
|
1449
1457
|
for (const theme of themes) {
|
|
1450
|
-
const
|
|
1451
|
-
const
|
|
1458
|
+
const themeDir = path__default.default.join(getThemesDir(), theme);
|
|
1459
|
+
const candidates = ["theme.config.ts", "bundle-entry.ts", "manifest.ts"];
|
|
1460
|
+
let manifestContent = "";
|
|
1461
|
+
for (const candidate of candidates) {
|
|
1462
|
+
const candidatePath = path__default.default.join(themeDir, candidate);
|
|
1463
|
+
if (fs__default.default.existsSync(candidatePath)) {
|
|
1464
|
+
manifestContent = fs__default.default.readFileSync(candidatePath, "utf-8");
|
|
1465
|
+
break;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1452
1468
|
const nameMatch = manifestContent.match(/name:\s*["'](.+)["']/);
|
|
1453
1469
|
const versionMatch = manifestContent.match(/version:\s*["'](.+)["']/);
|
|
1454
1470
|
const descMatch = manifestContent.match(/description:\s*["'](.+)["']/);
|
|
@@ -1581,13 +1597,11 @@ function getS3Client() {
|
|
|
1581
1597
|
return new clientS3.S3Client({
|
|
1582
1598
|
endpoint: endpointUrl,
|
|
1583
1599
|
region: "us-east-1",
|
|
1584
|
-
// MinIO doesn't use real regions
|
|
1585
1600
|
credentials: {
|
|
1586
1601
|
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
1587
1602
|
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
1588
1603
|
},
|
|
1589
1604
|
forcePathStyle: true
|
|
1590
|
-
// Required for MinIO
|
|
1591
1605
|
});
|
|
1592
1606
|
}
|
|
1593
1607
|
if (adapterMode === "local") {
|
|
@@ -1657,36 +1671,40 @@ async function readManifest() {
|
|
|
1657
1671
|
"No manifest.ts or package.json found. Are you in a theme directory?"
|
|
1658
1672
|
);
|
|
1659
1673
|
}
|
|
1660
|
-
function
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
".ts": "text/plain"
|
|
1675
|
-
};
|
|
1676
|
-
return types[ext] || "application/octet-stream";
|
|
1674
|
+
async function createZipFromDir(sourceDir, outputPath, excludePatterns = []) {
|
|
1675
|
+
return new Promise((resolve, reject) => {
|
|
1676
|
+
const output = fs__default.default.createWriteStream(outputPath);
|
|
1677
|
+
const archive = archiver__default.default("zip", { zlib: { level: 6 } });
|
|
1678
|
+
output.on("close", () => resolve());
|
|
1679
|
+
archive.on("error", (err) => reject(err));
|
|
1680
|
+
archive.pipe(output);
|
|
1681
|
+
archive.glob("**/*", {
|
|
1682
|
+
cwd: sourceDir,
|
|
1683
|
+
dot: true,
|
|
1684
|
+
ignore: excludePatterns
|
|
1685
|
+
});
|
|
1686
|
+
archive.finalize();
|
|
1687
|
+
});
|
|
1677
1688
|
}
|
|
1678
|
-
async function
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
)
|
|
1689
|
+
async function findSourceDir(themeId, explicitDir) {
|
|
1690
|
+
if (explicitDir) {
|
|
1691
|
+
if (await fs__default.default.pathExists(explicitDir)) return explicitDir;
|
|
1692
|
+
return null;
|
|
1693
|
+
}
|
|
1694
|
+
const searchPaths = [
|
|
1695
|
+
process.cwd(),
|
|
1696
|
+
path__default.default.resolve(process.cwd(), `../../themes/${themeId}`),
|
|
1697
|
+
path__default.default.resolve(process.cwd(), `../themes/${themeId}`)
|
|
1698
|
+
];
|
|
1699
|
+
const markers = ["theme.config.ts", "bundle-entry.ts"];
|
|
1700
|
+
for (const dir of searchPaths) {
|
|
1701
|
+
for (const marker of markers) {
|
|
1702
|
+
if (await fs__default.default.pathExists(path__default.default.join(dir, marker))) {
|
|
1703
|
+
return dir;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
return null;
|
|
1690
1708
|
}
|
|
1691
1709
|
async function updateLatestPointer(s3Client, bucket, themeId, version) {
|
|
1692
1710
|
const latestData = {
|
|
@@ -1704,12 +1722,18 @@ async function updateLatestPointer(s3Client, bucket, themeId, version) {
|
|
|
1704
1722
|
}
|
|
1705
1723
|
async function uploadCommand(options) {
|
|
1706
1724
|
logger.header("Upload Theme to S3");
|
|
1707
|
-
ensureOneXProject();
|
|
1708
1725
|
const spinner = ora__default.default("Preparing theme upload...").start();
|
|
1709
1726
|
try {
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1727
|
+
let themeId;
|
|
1728
|
+
let version;
|
|
1729
|
+
if (options.theme) {
|
|
1730
|
+
themeId = options.theme;
|
|
1731
|
+
version = options.version || "1.0.0";
|
|
1732
|
+
} else {
|
|
1733
|
+
const manifest = await readManifest();
|
|
1734
|
+
themeId = manifest.themeId;
|
|
1735
|
+
version = options.version || manifest.version || "1.0.0";
|
|
1736
|
+
}
|
|
1713
1737
|
spinner.text = `Found theme: ${themeId}@${version}`;
|
|
1714
1738
|
const bucket = options.bucket || getBucketName(options.environment);
|
|
1715
1739
|
const s3Client = getS3Client();
|
|
@@ -1730,67 +1754,113 @@ async function uploadCommand(options) {
|
|
|
1730
1754
|
process.exit(1);
|
|
1731
1755
|
}
|
|
1732
1756
|
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
1733
|
-
spinner.start(
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
spinner.fail(chalk4__default.default.red("No files found in compiled theme directory"));
|
|
1741
|
-
process.exit(1);
|
|
1742
|
-
}
|
|
1743
|
-
spinner.succeed(`Found ${files.length} files to upload`);
|
|
1757
|
+
spinner.start("Creating bundle.zip...");
|
|
1758
|
+
const tmpDir = os__default.default.tmpdir();
|
|
1759
|
+
const bundleZipPath = path__default.default.join(tmpDir, `${themeId}-${version}-bundle.zip`);
|
|
1760
|
+
await createZipFromDir(compiledDir, bundleZipPath);
|
|
1761
|
+
const bundleZipBuffer = await fs__default.default.readFile(bundleZipPath);
|
|
1762
|
+
const bundleSizeMB = (bundleZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
1763
|
+
spinner.succeed(`Created bundle.zip (${bundleSizeMB} MB)`);
|
|
1744
1764
|
if (options.dryRun) {
|
|
1745
|
-
spinner.info(chalk4__default.default.yellow("Dry run mode
|
|
1746
|
-
console.log(
|
|
1747
|
-
|
|
1748
|
-
displayFiles.forEach((file) => console.log(chalk4__default.default.gray(` - ${file}`)));
|
|
1749
|
-
if (files.length > 10) {
|
|
1750
|
-
console.log(chalk4__default.default.gray(` ... and ${files.length - 10} more files
|
|
1751
|
-
`));
|
|
1752
|
-
}
|
|
1753
|
-
console.log(chalk4__default.default.cyan(`
|
|
1754
|
-
S3 bucket: ${bucket}`));
|
|
1765
|
+
spinner.info(chalk4__default.default.yellow("Dry run mode \u2014 no files will be uploaded"));
|
|
1766
|
+
console.log();
|
|
1767
|
+
console.log(chalk4__default.default.gray(` bundle.zip: ${bundleSizeMB} MB`));
|
|
1755
1768
|
console.log(
|
|
1756
|
-
chalk4__default.default.cyan(
|
|
1757
|
-
`
|
|
1769
|
+
chalk4__default.default.cyan(
|
|
1770
|
+
` S3 path: s3://${bucket}/themes/${themeId}/${version}/bundle.zip`
|
|
1771
|
+
)
|
|
1758
1772
|
);
|
|
1773
|
+
if (!options.skipSource) {
|
|
1774
|
+
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
1775
|
+
if (sourceDir) {
|
|
1776
|
+
console.log(chalk4__default.default.gray(` source dir: ${sourceDir}`));
|
|
1777
|
+
console.log(
|
|
1778
|
+
chalk4__default.default.cyan(
|
|
1779
|
+
` S3 path: s3://${bucket}/themes/${themeId}/${version}/source.zip`
|
|
1780
|
+
)
|
|
1781
|
+
);
|
|
1782
|
+
} else {
|
|
1783
|
+
console.log(
|
|
1784
|
+
chalk4__default.default.yellow(" source dir: not found (source.zip will be skipped)")
|
|
1785
|
+
);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
console.log();
|
|
1789
|
+
await fs__default.default.remove(bundleZipPath);
|
|
1759
1790
|
return;
|
|
1760
1791
|
}
|
|
1761
|
-
spinner.start(
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1792
|
+
spinner.start("Uploading bundle.zip to S3...");
|
|
1793
|
+
const bundleS3Key = `themes/${themeId}/${version}/bundle.zip`;
|
|
1794
|
+
await s3Client.send(
|
|
1795
|
+
new clientS3.PutObjectCommand({
|
|
1796
|
+
Bucket: bucket,
|
|
1797
|
+
Key: bundleS3Key,
|
|
1798
|
+
Body: bundleZipBuffer,
|
|
1799
|
+
ContentType: "application/zip"
|
|
1800
|
+
})
|
|
1801
|
+
);
|
|
1802
|
+
spinner.succeed(
|
|
1803
|
+
`Uploaded bundle.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${bundleS3Key}`)}`
|
|
1804
|
+
);
|
|
1805
|
+
await fs__default.default.remove(bundleZipPath);
|
|
1806
|
+
let sourceUploaded = false;
|
|
1807
|
+
if (!options.skipSource) {
|
|
1808
|
+
spinner.start("Looking for source directory...");
|
|
1809
|
+
const sourceDir = await findSourceDir(themeId, options.sourceDir);
|
|
1810
|
+
if (sourceDir) {
|
|
1811
|
+
spinner.succeed(`Found source at: ${sourceDir}`);
|
|
1812
|
+
spinner.start("Creating source.zip...");
|
|
1813
|
+
const sourceZipPath = path__default.default.join(
|
|
1814
|
+
tmpDir,
|
|
1815
|
+
`${themeId}-${version}-source.zip`
|
|
1816
|
+
);
|
|
1817
|
+
await createZipFromDir(sourceDir, sourceZipPath, [
|
|
1818
|
+
"node_modules/**",
|
|
1819
|
+
"dist/**",
|
|
1820
|
+
".git/**",
|
|
1821
|
+
"*.zip",
|
|
1822
|
+
".next/**",
|
|
1823
|
+
".turbo/**"
|
|
1824
|
+
]);
|
|
1825
|
+
const sourceZipBuffer = await fs__default.default.readFile(sourceZipPath);
|
|
1826
|
+
const sourceSizeMB = (sourceZipBuffer.length / 1024 / 1024).toFixed(2);
|
|
1827
|
+
spinner.succeed(`Created source.zip (${sourceSizeMB} MB)`);
|
|
1828
|
+
spinner.start("Uploading source.zip to S3...");
|
|
1829
|
+
const sourceS3Key = `themes/${themeId}/${version}/source.zip`;
|
|
1830
|
+
await s3Client.send(
|
|
1831
|
+
new clientS3.PutObjectCommand({
|
|
1832
|
+
Bucket: bucket,
|
|
1833
|
+
Key: sourceS3Key,
|
|
1834
|
+
Body: sourceZipBuffer,
|
|
1835
|
+
ContentType: "application/zip"
|
|
1836
|
+
})
|
|
1837
|
+
);
|
|
1838
|
+
spinner.succeed(
|
|
1839
|
+
`Uploaded source.zip ${chalk4__default.default.gray(`\u2192 s3://${bucket}/${sourceS3Key}`)}`
|
|
1840
|
+
);
|
|
1841
|
+
await fs__default.default.remove(sourceZipPath);
|
|
1842
|
+
sourceUploaded = true;
|
|
1843
|
+
} else {
|
|
1844
|
+
spinner.warn(
|
|
1845
|
+
chalk4__default.default.yellow("Source directory not found \u2014 skipping source.zip")
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1781
1848
|
}
|
|
1782
|
-
spinner.succeed(`Uploaded ${total} files to S3`);
|
|
1783
1849
|
spinner.start("Updating latest.json pointer...");
|
|
1784
1850
|
await updateLatestPointer(s3Client, bucket, themeId, version);
|
|
1785
1851
|
spinner.succeed("Updated latest.json pointer");
|
|
1786
1852
|
console.log();
|
|
1787
|
-
logger.success(chalk4__default.default.green.bold("
|
|
1853
|
+
logger.success(chalk4__default.default.green.bold("Theme uploaded successfully!"));
|
|
1788
1854
|
console.log();
|
|
1789
1855
|
console.log(
|
|
1790
1856
|
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${version}`)
|
|
1791
1857
|
);
|
|
1792
1858
|
console.log(chalk4__default.default.cyan(" Bucket: ") + chalk4__default.default.white(bucket));
|
|
1793
|
-
console.log(
|
|
1859
|
+
console.log(
|
|
1860
|
+
chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(
|
|
1861
|
+
`bundle.zip${sourceUploaded ? " + source.zip" : ""}`
|
|
1862
|
+
)
|
|
1863
|
+
);
|
|
1794
1864
|
console.log(
|
|
1795
1865
|
chalk4__default.default.cyan(" Path: ") + chalk4__default.default.gray(`s3://${bucket}/themes/${themeId}/${version}/`)
|
|
1796
1866
|
);
|
|
@@ -1894,79 +1964,45 @@ async function resolveLatestVersion(s3Client, bucket, themeId) {
|
|
|
1894
1964
|
);
|
|
1895
1965
|
}
|
|
1896
1966
|
}
|
|
1897
|
-
async function
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
`Failed to download manifest for ${themeId}@${version}: ${error.message}
|
|
1910
|
-
The theme may not exist in S3 bucket "${bucket}".`
|
|
1911
|
-
);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
async function downloadFile(s3Client, bucket, themeId, version, file, outputDir) {
|
|
1915
|
-
const s3Key = `themes/${themeId}/${version}/${file}`;
|
|
1916
|
-
const localPath = path__default.default.join(outputDir, file);
|
|
1917
|
-
await fs__default.default.ensureDir(path__default.default.dirname(localPath));
|
|
1918
|
-
try {
|
|
1919
|
-
const response = await s3Client.send(
|
|
1920
|
-
new clientS3.GetObjectCommand({
|
|
1921
|
-
Bucket: bucket,
|
|
1922
|
-
Key: s3Key
|
|
1923
|
-
})
|
|
1924
|
-
);
|
|
1925
|
-
const content = await streamToBuffer(response.Body);
|
|
1926
|
-
await fs__default.default.writeFile(localPath, content);
|
|
1927
|
-
} catch (error) {
|
|
1928
|
-
throw new Error(`Failed to download ${file}: ${error.message}`);
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
function collectFilesToDownload(manifest) {
|
|
1932
|
-
const files = ["manifest.json"];
|
|
1933
|
-
if (manifest.output) {
|
|
1934
|
-
if (manifest.output.entry) {
|
|
1935
|
-
files.push(manifest.output.entry);
|
|
1936
|
-
}
|
|
1937
|
-
if (manifest.output.chunks) {
|
|
1938
|
-
files.push(...manifest.output.chunks);
|
|
1939
|
-
}
|
|
1940
|
-
if (manifest.output.assets) {
|
|
1941
|
-
files.push(...manifest.output.assets);
|
|
1967
|
+
async function createCompatibilityFiles(outputDir, manifest) {
|
|
1968
|
+
var _a;
|
|
1969
|
+
const entryFile = ((_a = manifest.output) == null ? void 0 : _a.entry) || "bundle-entry.js";
|
|
1970
|
+
if (entryFile !== "bundle-entry.js" && entryFile.startsWith("bundle-entry-")) {
|
|
1971
|
+
const hashedPath = path__default.default.join(outputDir, entryFile);
|
|
1972
|
+
const stablePath = path__default.default.join(outputDir, "bundle-entry.js");
|
|
1973
|
+
if (await fs__default.default.pathExists(hashedPath)) {
|
|
1974
|
+
await fs__default.default.copy(hashedPath, stablePath);
|
|
1975
|
+
const mapPath = hashedPath + ".map";
|
|
1976
|
+
if (await fs__default.default.pathExists(mapPath)) {
|
|
1977
|
+
await fs__default.default.copy(mapPath, stablePath + ".map");
|
|
1978
|
+
}
|
|
1942
1979
|
}
|
|
1943
1980
|
}
|
|
1944
|
-
return files;
|
|
1945
|
-
}
|
|
1946
|
-
async function createCompatibilityFiles(outputDir) {
|
|
1947
1981
|
const sectionsRegistryPath = path__default.default.join(outputDir, "sections-registry.js");
|
|
1948
1982
|
const content = `// Re-export all sections from bundle-entry
|
|
1949
1983
|
// This file exists to maintain compatibility with the import path
|
|
1950
1984
|
export * from './bundle-entry.js';
|
|
1951
1985
|
`;
|
|
1952
1986
|
await fs__default.default.writeFile(sectionsRegistryPath, content, "utf-8");
|
|
1987
|
+
const pkgJsonPath = path__default.default.join(outputDir, "package.json");
|
|
1988
|
+
await fs__default.default.writeFile(pkgJsonPath, '{\n "type": "module"\n}\n', "utf-8");
|
|
1953
1989
|
}
|
|
1954
1990
|
function showDownloadFailureHelp(themeId, bucket) {
|
|
1955
1991
|
console.log();
|
|
1956
|
-
logger.error(chalk4__default.default.red.bold("
|
|
1992
|
+
logger.error(chalk4__default.default.red.bold("Theme download failed"));
|
|
1957
1993
|
console.log();
|
|
1958
1994
|
console.log(chalk4__default.default.yellow("Possible reasons:"));
|
|
1959
1995
|
console.log(chalk4__default.default.gray(" 1. Theme not uploaded to S3 yet"));
|
|
1960
1996
|
console.log(chalk4__default.default.gray(" 2. AWS credentials not configured correctly"));
|
|
1961
1997
|
console.log(chalk4__default.default.gray(" 3. Bucket name or region is incorrect"));
|
|
1962
|
-
console.log(chalk4__default.default.gray(" 4.
|
|
1998
|
+
console.log(chalk4__default.default.gray(" 4. bundle.zip is missing or corrupted"));
|
|
1963
1999
|
console.log();
|
|
1964
2000
|
console.log(chalk4__default.default.cyan.bold("To fix this:"));
|
|
1965
2001
|
console.log();
|
|
1966
2002
|
console.log(chalk4__default.default.white("1. Compile and upload the theme:"));
|
|
1967
2003
|
console.log(chalk4__default.default.gray(` cd themes/${themeId}`));
|
|
1968
2004
|
console.log(chalk4__default.default.gray(" pnpm build"));
|
|
1969
|
-
console.log(chalk4__default.default.gray("
|
|
2005
|
+
console.log(chalk4__default.default.gray(" onex upload"));
|
|
1970
2006
|
console.log();
|
|
1971
2007
|
console.log(chalk4__default.default.white("2. Verify AWS credentials are set:"));
|
|
1972
2008
|
console.log(
|
|
@@ -1982,7 +2018,11 @@ function showDownloadFailureHelp(themeId, bucket) {
|
|
|
1982
2018
|
);
|
|
1983
2019
|
console.log();
|
|
1984
2020
|
console.log(chalk4__default.default.white("4. Verify theme exists in S3:"));
|
|
1985
|
-
console.log(
|
|
2021
|
+
console.log(
|
|
2022
|
+
chalk4__default.default.gray(
|
|
2023
|
+
` aws s3 ls s3://${bucket}/themes/${themeId}/`
|
|
2024
|
+
)
|
|
2025
|
+
);
|
|
1986
2026
|
console.log();
|
|
1987
2027
|
}
|
|
1988
2028
|
async function downloadCommand(options) {
|
|
@@ -2010,55 +2050,44 @@ async function downloadCommand(options) {
|
|
|
2010
2050
|
spinner.succeed(
|
|
2011
2051
|
`Resolved latest version: ${chalk4__default.default.cyan(resolvedVersion)}`
|
|
2012
2052
|
);
|
|
2013
|
-
spinner.start("Downloading manifest...");
|
|
2014
2053
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2054
|
+
spinner.start(
|
|
2055
|
+
`Downloading bundle.zip for ${themeId}@${resolvedVersion}...`
|
|
2056
|
+
);
|
|
2057
|
+
const s3Key = `themes/${themeId}/${resolvedVersion}/bundle.zip`;
|
|
2058
|
+
const response = await s3Client.send(
|
|
2059
|
+
new clientS3.GetObjectCommand({
|
|
2060
|
+
Bucket: bucket,
|
|
2061
|
+
Key: s3Key
|
|
2062
|
+
})
|
|
2020
2063
|
);
|
|
2021
|
-
|
|
2022
|
-
|
|
2064
|
+
const zipBuffer = await streamToBuffer(response.Body);
|
|
2065
|
+
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
2066
|
+
spinner.succeed(`Downloaded bundle.zip (${sizeMB} MB)`);
|
|
2067
|
+
spinner.start("Extracting bundle...");
|
|
2023
2068
|
await fs__default.default.remove(outputDir);
|
|
2024
2069
|
await fs__default.default.ensureDir(outputDir);
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
const
|
|
2028
|
-
|
|
2029
|
-
const
|
|
2030
|
-
const
|
|
2031
|
-
|
|
2032
|
-
const batch = files.slice(i, i + batchSize);
|
|
2033
|
-
await Promise.all(
|
|
2034
|
-
batch.map(async (file) => {
|
|
2035
|
-
await downloadFile(
|
|
2036
|
-
s3Client,
|
|
2037
|
-
bucket,
|
|
2038
|
-
themeId,
|
|
2039
|
-
resolvedVersion,
|
|
2040
|
-
file,
|
|
2041
|
-
outputDir
|
|
2042
|
-
);
|
|
2043
|
-
downloaded++;
|
|
2044
|
-
spinner.text = `Downloading... ${downloaded}/${total} files (${Math.round(downloaded / total * 100)}%)`;
|
|
2045
|
-
})
|
|
2046
|
-
);
|
|
2047
|
-
}
|
|
2048
|
-
spinner.succeed(`Downloaded ${total} files`);
|
|
2049
|
-
await createCompatibilityFiles(outputDir);
|
|
2070
|
+
const zip = new AdmZip__default.default(zipBuffer);
|
|
2071
|
+
zip.extractAllTo(outputDir, true);
|
|
2072
|
+
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
2073
|
+
spinner.succeed(`Extracted ${entries.length} files to ${outputDir}`);
|
|
2074
|
+
const manifestPath = path__default.default.join(outputDir, "manifest.json");
|
|
2075
|
+
const manifest = await fs__default.default.readJson(manifestPath);
|
|
2076
|
+
await createCompatibilityFiles(outputDir, manifest);
|
|
2050
2077
|
console.log();
|
|
2051
|
-
logger.success(chalk4__default.default.green.bold("
|
|
2078
|
+
logger.success(chalk4__default.default.green.bold("Theme downloaded successfully!"));
|
|
2052
2079
|
console.log();
|
|
2053
2080
|
console.log(
|
|
2054
2081
|
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeId}@${resolvedVersion}`)
|
|
2055
2082
|
);
|
|
2056
2083
|
console.log(chalk4__default.default.cyan(" Bucket: ") + chalk4__default.default.white(bucket));
|
|
2057
2084
|
console.log(chalk4__default.default.cyan(" Output: ") + chalk4__default.default.white(outputDir));
|
|
2058
|
-
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2085
|
+
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
2086
|
+
if (manifest.counts) {
|
|
2087
|
+
console.log(
|
|
2088
|
+
chalk4__default.default.cyan(" Sections:") + chalk4__default.default.white(` ${manifest.counts.sections}`)
|
|
2089
|
+
);
|
|
2090
|
+
}
|
|
2062
2091
|
console.log();
|
|
2063
2092
|
} catch (error) {
|
|
2064
2093
|
spinner.fail(chalk4__default.default.red("Download failed"));
|
|
@@ -2069,9 +2098,214 @@ async function downloadCommand(options) {
|
|
|
2069
2098
|
process.exit(1);
|
|
2070
2099
|
}
|
|
2071
2100
|
}
|
|
2101
|
+
function getS3Client3() {
|
|
2102
|
+
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
2103
|
+
if (adapterMode === "vps") {
|
|
2104
|
+
const endpoint = process.env.MINIO_ENDPOINT || "localhost:9000";
|
|
2105
|
+
const secure = process.env.MINIO_SECURE === "true";
|
|
2106
|
+
const endpointUrl = endpoint.startsWith("http") ? endpoint : `${secure ? "https" : "http"}://${endpoint}`;
|
|
2107
|
+
return new clientS3.S3Client({
|
|
2108
|
+
endpoint: endpointUrl,
|
|
2109
|
+
region: "us-east-1",
|
|
2110
|
+
credentials: {
|
|
2111
|
+
accessKeyId: process.env.MINIO_ACCESS_KEY || "minioadmin",
|
|
2112
|
+
secretAccessKey: process.env.MINIO_SECRET_KEY || "minioadmin"
|
|
2113
|
+
},
|
|
2114
|
+
forcePathStyle: true
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
if (adapterMode === "local") {
|
|
2118
|
+
return new clientS3.S3Client({
|
|
2119
|
+
endpoint: "http://localhost:4569",
|
|
2120
|
+
region: "ap-southeast-1",
|
|
2121
|
+
credentials: {
|
|
2122
|
+
accessKeyId: "S3RVER",
|
|
2123
|
+
secretAccessKey: "S3RVER"
|
|
2124
|
+
},
|
|
2125
|
+
forcePathStyle: true
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
return new clientS3.S3Client({
|
|
2129
|
+
region: process.env.AWS_REGION || "ap-southeast-1"
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
function getBucketName3(env) {
|
|
2133
|
+
if (process.env.BUCKET_NAME) {
|
|
2134
|
+
return process.env.BUCKET_NAME;
|
|
2135
|
+
}
|
|
2136
|
+
const environment = env || process.env.ENVIRONMENT || "staging";
|
|
2137
|
+
return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
|
|
2138
|
+
}
|
|
2139
|
+
async function streamToString2(stream) {
|
|
2140
|
+
const chunks = [];
|
|
2141
|
+
try {
|
|
2142
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
2143
|
+
const chunk = temp.value;
|
|
2144
|
+
chunks.push(Buffer.from(chunk));
|
|
2145
|
+
}
|
|
2146
|
+
} catch (temp) {
|
|
2147
|
+
error = [temp];
|
|
2148
|
+
} finally {
|
|
2149
|
+
try {
|
|
2150
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
2151
|
+
} finally {
|
|
2152
|
+
if (error)
|
|
2153
|
+
throw error[0];
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
2157
|
+
}
|
|
2158
|
+
async function streamToBuffer2(stream) {
|
|
2159
|
+
const chunks = [];
|
|
2160
|
+
try {
|
|
2161
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
2162
|
+
const chunk = temp.value;
|
|
2163
|
+
chunks.push(Buffer.from(chunk));
|
|
2164
|
+
}
|
|
2165
|
+
} catch (temp) {
|
|
2166
|
+
error = [temp];
|
|
2167
|
+
} finally {
|
|
2168
|
+
try {
|
|
2169
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
2170
|
+
} finally {
|
|
2171
|
+
if (error)
|
|
2172
|
+
throw error[0];
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
return Buffer.concat(chunks);
|
|
2176
|
+
}
|
|
2177
|
+
async function resolveLatestVersion2(s3Client, bucket, themeId) {
|
|
2178
|
+
try {
|
|
2179
|
+
const response = await s3Client.send(
|
|
2180
|
+
new clientS3.GetObjectCommand({
|
|
2181
|
+
Bucket: bucket,
|
|
2182
|
+
Key: `themes/${themeId}/latest.json`
|
|
2183
|
+
})
|
|
2184
|
+
);
|
|
2185
|
+
const body = await streamToString2(response.Body);
|
|
2186
|
+
return JSON.parse(body).version;
|
|
2187
|
+
} catch (error) {
|
|
2188
|
+
throw new Error(
|
|
2189
|
+
`Failed to resolve latest version for theme "${themeId}": ${error.message}`
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
function runInstall(cwd) {
|
|
2194
|
+
return new Promise((resolve) => {
|
|
2195
|
+
const proc = child_process.spawn("pnpm", ["install"], {
|
|
2196
|
+
cwd,
|
|
2197
|
+
stdio: "inherit",
|
|
2198
|
+
shell: true
|
|
2199
|
+
});
|
|
2200
|
+
proc.on("close", (code) => resolve(code === 0));
|
|
2201
|
+
proc.on("error", () => resolve(false));
|
|
2202
|
+
});
|
|
2203
|
+
}
|
|
2204
|
+
async function cloneCommand(themeName, options) {
|
|
2205
|
+
logger.header("Clone Theme Source");
|
|
2206
|
+
const spinner = ora__default.default("Initializing clone...").start();
|
|
2207
|
+
try {
|
|
2208
|
+
const bucket = options.bucket || getBucketName3(options.environment);
|
|
2209
|
+
const outputDir = options.output || path__default.default.resolve(process.cwd(), themeName);
|
|
2210
|
+
const s3Client = getS3Client3();
|
|
2211
|
+
if (await fs__default.default.pathExists(outputDir)) {
|
|
2212
|
+
spinner.fail(
|
|
2213
|
+
chalk4__default.default.red(`Directory already exists: ${outputDir}`)
|
|
2214
|
+
);
|
|
2215
|
+
logger.info(
|
|
2216
|
+
chalk4__default.default.gray(
|
|
2217
|
+
"Use -o to specify a different output directory, or remove the existing directory."
|
|
2218
|
+
)
|
|
2219
|
+
);
|
|
2220
|
+
process.exit(1);
|
|
2221
|
+
}
|
|
2222
|
+
let version = options.version || "latest";
|
|
2223
|
+
if (version === "latest") {
|
|
2224
|
+
spinner.text = "Resolving latest version...";
|
|
2225
|
+
version = await resolveLatestVersion2(s3Client, bucket, themeName);
|
|
2226
|
+
spinner.succeed(`Resolved latest version: ${chalk4__default.default.cyan(version)}`);
|
|
2227
|
+
}
|
|
2228
|
+
spinner.start(
|
|
2229
|
+
`Downloading source.zip for ${themeName}@${version}...`
|
|
2230
|
+
);
|
|
2231
|
+
const s3Key = `themes/${themeName}/${version}/source.zip`;
|
|
2232
|
+
let zipBuffer;
|
|
2233
|
+
try {
|
|
2234
|
+
const response = await s3Client.send(
|
|
2235
|
+
new clientS3.GetObjectCommand({
|
|
2236
|
+
Bucket: bucket,
|
|
2237
|
+
Key: s3Key
|
|
2238
|
+
})
|
|
2239
|
+
);
|
|
2240
|
+
zipBuffer = await streamToBuffer2(response.Body);
|
|
2241
|
+
} catch (error) {
|
|
2242
|
+
spinner.fail(chalk4__default.default.red(`Source not found: s3://${bucket}/${s3Key}`));
|
|
2243
|
+
console.log();
|
|
2244
|
+
console.log(
|
|
2245
|
+
chalk4__default.default.yellow("The theme source may not have been uploaded yet.")
|
|
2246
|
+
);
|
|
2247
|
+
console.log(
|
|
2248
|
+
chalk4__default.default.gray(
|
|
2249
|
+
`Upload source with: onex upload --theme ${themeName}`
|
|
2250
|
+
)
|
|
2251
|
+
);
|
|
2252
|
+
console.log();
|
|
2253
|
+
process.exit(1);
|
|
2254
|
+
}
|
|
2255
|
+
const sizeMB = (zipBuffer.length / 1024 / 1024).toFixed(2);
|
|
2256
|
+
spinner.succeed(`Downloaded source.zip (${sizeMB} MB)`);
|
|
2257
|
+
spinner.start(`Extracting to ${outputDir}...`);
|
|
2258
|
+
await fs__default.default.ensureDir(outputDir);
|
|
2259
|
+
const zip = new AdmZip__default.default(zipBuffer);
|
|
2260
|
+
zip.extractAllTo(outputDir, true);
|
|
2261
|
+
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
2262
|
+
spinner.succeed(`Extracted ${entries.length} files`);
|
|
2263
|
+
if (options.install !== false) {
|
|
2264
|
+
const hasPkgJson = await fs__default.default.pathExists(
|
|
2265
|
+
path__default.default.join(outputDir, "package.json")
|
|
2266
|
+
);
|
|
2267
|
+
if (hasPkgJson) {
|
|
2268
|
+
spinner.start("Installing dependencies...");
|
|
2269
|
+
const success = await runInstall(outputDir);
|
|
2270
|
+
if (success) {
|
|
2271
|
+
spinner.succeed("Dependencies installed");
|
|
2272
|
+
} else {
|
|
2273
|
+
spinner.warn(
|
|
2274
|
+
chalk4__default.default.yellow(
|
|
2275
|
+
"Failed to install dependencies \u2014 run 'pnpm install' manually"
|
|
2276
|
+
)
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
console.log();
|
|
2282
|
+
logger.success(chalk4__default.default.green.bold("Theme cloned successfully!"));
|
|
2283
|
+
console.log();
|
|
2284
|
+
console.log(
|
|
2285
|
+
chalk4__default.default.cyan(" Theme: ") + chalk4__default.default.white(`${themeName}@${version}`)
|
|
2286
|
+
);
|
|
2287
|
+
console.log(chalk4__default.default.cyan(" Location: ") + chalk4__default.default.white(outputDir));
|
|
2288
|
+
console.log(chalk4__default.default.cyan(" Files: ") + chalk4__default.default.white(entries.length));
|
|
2289
|
+
console.log();
|
|
2290
|
+
console.log(chalk4__default.default.cyan("Next steps:"));
|
|
2291
|
+
console.log(
|
|
2292
|
+
chalk4__default.default.gray(` cd ${path__default.default.relative(process.cwd(), outputDir)}`)
|
|
2293
|
+
);
|
|
2294
|
+
if (options.install === false) {
|
|
2295
|
+
console.log(chalk4__default.default.gray(" pnpm install"));
|
|
2296
|
+
}
|
|
2297
|
+
console.log(chalk4__default.default.gray(" onex build"));
|
|
2298
|
+
console.log();
|
|
2299
|
+
} catch (error) {
|
|
2300
|
+
spinner.fail(chalk4__default.default.red(`Clone failed: ${error.message}`));
|
|
2301
|
+
logger.error(error.stack || error.message);
|
|
2302
|
+
process.exit(1);
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2072
2305
|
|
|
2073
2306
|
exports.Logger = Logger;
|
|
2074
2307
|
exports.buildCommand = buildCommand;
|
|
2308
|
+
exports.cloneCommand = cloneCommand;
|
|
2075
2309
|
exports.copyTemplate = copyTemplate;
|
|
2076
2310
|
exports.createBlockCommand = createBlockCommand;
|
|
2077
2311
|
exports.createComponentCommand = createComponentCommand;
|