@onexapis/cli 1.0.3 → 1.1.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/README.md +65 -63
- package/dist/cli.js +1117 -114
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1092 -112
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +978 -242
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +812 -95
- package/dist/index.mjs.map +1 -1
- package/dist/preview/preview-app.tsx +368 -0
- package/package.json +7 -2
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import chalk4 from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import * as esbuild from 'esbuild';
|
|
1
4
|
import path from 'path';
|
|
5
|
+
import fs6 from 'fs/promises';
|
|
6
|
+
import crypto from 'crypto';
|
|
7
|
+
import { glob } from 'glob';
|
|
2
8
|
import fs2 from 'fs';
|
|
3
9
|
import { execSync, spawn } from 'child_process';
|
|
4
10
|
import inquirer from 'inquirer';
|
|
5
|
-
import chalk4 from 'chalk';
|
|
6
|
-
import ora from 'ora';
|
|
7
11
|
import fs from 'fs-extra';
|
|
8
12
|
import ejs from 'ejs';
|
|
9
13
|
import { PutObjectCommand, GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
@@ -11,6 +15,8 @@ import os from 'os';
|
|
|
11
15
|
import archiver from 'archiver';
|
|
12
16
|
import AdmZip from 'adm-zip';
|
|
13
17
|
|
|
18
|
+
var __defProp = Object.defineProperty;
|
|
19
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
20
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
15
21
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
16
22
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -18,58 +24,644 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
18
24
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
19
25
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
20
26
|
});
|
|
27
|
+
var __esm = (fn, res) => function __init() {
|
|
28
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
29
|
+
};
|
|
30
|
+
var __export = (target, all) => {
|
|
31
|
+
for (var name in all)
|
|
32
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
33
|
+
};
|
|
21
34
|
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
22
|
-
var Logger
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
var Logger, logger;
|
|
36
|
+
var init_logger = __esm({
|
|
37
|
+
"src/utils/logger.ts"() {
|
|
38
|
+
Logger = class {
|
|
39
|
+
constructor() {
|
|
40
|
+
this.spinner = null;
|
|
41
|
+
}
|
|
42
|
+
success(message) {
|
|
43
|
+
console.log(chalk4.green("\u2713"), message);
|
|
44
|
+
}
|
|
45
|
+
error(message) {
|
|
46
|
+
console.log(chalk4.red("\u2717"), message);
|
|
47
|
+
}
|
|
48
|
+
warning(message) {
|
|
49
|
+
console.log(chalk4.yellow("\u26A0"), message);
|
|
50
|
+
}
|
|
51
|
+
info(message) {
|
|
52
|
+
console.log(chalk4.blue("\u2139"), message);
|
|
53
|
+
}
|
|
54
|
+
log(message) {
|
|
55
|
+
console.log(message);
|
|
56
|
+
}
|
|
57
|
+
startSpinner(message) {
|
|
58
|
+
this.spinner = ora(message).start();
|
|
59
|
+
}
|
|
60
|
+
stopSpinner(success = true, message) {
|
|
61
|
+
if (!this.spinner) return;
|
|
62
|
+
if (success) {
|
|
63
|
+
this.spinner.succeed(message);
|
|
64
|
+
} else {
|
|
65
|
+
this.spinner.fail(message);
|
|
66
|
+
}
|
|
67
|
+
this.spinner = null;
|
|
68
|
+
}
|
|
69
|
+
updateSpinner(message) {
|
|
70
|
+
if (this.spinner) {
|
|
71
|
+
this.spinner.text = message;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
newLine() {
|
|
75
|
+
console.log();
|
|
76
|
+
}
|
|
77
|
+
header(message) {
|
|
78
|
+
console.log();
|
|
79
|
+
console.log(chalk4.bold.cyan(message));
|
|
80
|
+
console.log(chalk4.cyan("=".repeat(message.length)));
|
|
81
|
+
console.log();
|
|
82
|
+
}
|
|
83
|
+
section(message) {
|
|
84
|
+
console.log();
|
|
85
|
+
console.log(chalk4.bold(message));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
logger = new Logger();
|
|
31
89
|
}
|
|
32
|
-
|
|
33
|
-
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/utils/compile-theme.ts
|
|
93
|
+
var compile_theme_exports = {};
|
|
94
|
+
__export(compile_theme_exports, {
|
|
95
|
+
compilePreviewRuntime: () => compilePreviewRuntime,
|
|
96
|
+
compileStandaloneTheme: () => compileStandaloneTheme,
|
|
97
|
+
compileStandaloneThemeDev: () => compileStandaloneThemeDev,
|
|
98
|
+
generateManifest: () => generateManifest2
|
|
99
|
+
});
|
|
100
|
+
async function resolveNodeModulesFile(startDir, relativePath) {
|
|
101
|
+
let dir = startDir;
|
|
102
|
+
while (true) {
|
|
103
|
+
const candidate = path.join(dir, "node_modules", relativePath);
|
|
104
|
+
try {
|
|
105
|
+
await fs6.access(candidate);
|
|
106
|
+
return candidate;
|
|
107
|
+
} catch (e) {
|
|
108
|
+
const parent = path.dirname(dir);
|
|
109
|
+
if (parent === dir) break;
|
|
110
|
+
dir = parent;
|
|
111
|
+
}
|
|
34
112
|
}
|
|
35
|
-
|
|
36
|
-
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
function createCoreGlobalPlugin(themePath) {
|
|
116
|
+
const exportsBySubpath = {};
|
|
117
|
+
return {
|
|
118
|
+
name: "core-global",
|
|
119
|
+
setup(build2) {
|
|
120
|
+
build2.onResolve({ filter: /^@onexapis\/core(\/.*)?$/ }, (args) => ({
|
|
121
|
+
path: args.path,
|
|
122
|
+
namespace: "core-global"
|
|
123
|
+
}));
|
|
124
|
+
build2.onLoad({ filter: /.*/, namespace: "core-global" }, async (args) => {
|
|
125
|
+
const match = args.path.match(/^@onexapis\/core(\/(.+))?$/);
|
|
126
|
+
const subpath = (match == null ? void 0 : match[2]) || "";
|
|
127
|
+
const moduleAccess = subpath ? `['${subpath}']` : "";
|
|
128
|
+
let namedExports = [];
|
|
129
|
+
const cacheKey = subpath || "__root__";
|
|
130
|
+
if (exportsBySubpath[cacheKey]) {
|
|
131
|
+
namedExports = exportsBySubpath[cacheKey];
|
|
132
|
+
} else {
|
|
133
|
+
const distFileName = subpath ? `${subpath}.mjs` : "index.mjs";
|
|
134
|
+
const distPath = await resolveNodeModulesFile(
|
|
135
|
+
themePath,
|
|
136
|
+
path.join("@onexapis", "core", "dist", distFileName)
|
|
137
|
+
);
|
|
138
|
+
try {
|
|
139
|
+
if (!distPath) throw new Error("not found");
|
|
140
|
+
const distContent = await fs6.readFile(distPath, "utf-8");
|
|
141
|
+
const exportMatches = distContent.matchAll(/export\s*\{([^}]+)\}/g);
|
|
142
|
+
for (const m of exportMatches) {
|
|
143
|
+
const names = m[1].split(",").map((n) => {
|
|
144
|
+
const parts = n.trim().split(/\s+as\s+/);
|
|
145
|
+
return (parts[1] || parts[0]).trim();
|
|
146
|
+
}).filter((n) => n.length > 0);
|
|
147
|
+
namedExports.push(...names);
|
|
148
|
+
}
|
|
149
|
+
namedExports = [...new Set(namedExports)];
|
|
150
|
+
} catch (e) {
|
|
151
|
+
}
|
|
152
|
+
exportsBySubpath[cacheKey] = namedExports;
|
|
153
|
+
}
|
|
154
|
+
const namedExportLines = namedExports.length > 0 ? `
|
|
155
|
+
export const {
|
|
156
|
+
${namedExports.join(",\n ")}
|
|
157
|
+
} = _module;
|
|
158
|
+
` : "";
|
|
159
|
+
return {
|
|
160
|
+
contents: `
|
|
161
|
+
if (!globalThis.__ONEX_CORE__) {
|
|
162
|
+
throw new Error('[Theme Bundle] @onexapis/core not initialized. Ensure globalThis.__ONEX_CORE__ is set before loading theme.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const _module = globalThis.__ONEX_CORE__${moduleAccess};
|
|
166
|
+
if (!_module) {
|
|
167
|
+
const subpath = ${subpath ? `'${subpath}'` : "null"};
|
|
168
|
+
const modulePath = subpath ? '/' + subpath : '';
|
|
169
|
+
const moduleKey = subpath ? '["' + subpath + '"]' : '';
|
|
170
|
+
throw new Error('[Theme Bundle] @onexapis/core' + modulePath + ' not available in globalThis.__ONEX_CORE__' + moduleKey);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default _module;
|
|
174
|
+
${namedExportLines}
|
|
175
|
+
`.trim(),
|
|
176
|
+
loader: "js"
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async function contentHashEntry(outputDir) {
|
|
183
|
+
const entryPath = path.join(outputDir, "bundle-entry.js");
|
|
184
|
+
const mapPath = path.join(outputDir, "bundle-entry.js.map");
|
|
185
|
+
const oldFiles = await glob("bundle-entry-*.js*", { cwd: outputDir });
|
|
186
|
+
for (const f of oldFiles) {
|
|
187
|
+
await fs6.unlink(path.join(outputDir, f));
|
|
37
188
|
}
|
|
38
|
-
|
|
39
|
-
|
|
189
|
+
let entryContent;
|
|
190
|
+
try {
|
|
191
|
+
entryContent = await fs6.readFile(entryPath, "utf-8");
|
|
192
|
+
} catch (e) {
|
|
193
|
+
const indexPath = path.join(outputDir, "index.js");
|
|
194
|
+
try {
|
|
195
|
+
entryContent = await fs6.readFile(indexPath, "utf-8");
|
|
196
|
+
} catch (e2) {
|
|
197
|
+
logger.warning("No entry file found in output, skipping content hash");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const hash2 = crypto.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
201
|
+
const hashedName2 = `bundle-entry-${hash2}.js`;
|
|
202
|
+
const indexMapPath = path.join(outputDir, "index.js.map");
|
|
203
|
+
const hashedMapName2 = `bundle-entry-${hash2}.js.map`;
|
|
204
|
+
entryContent = entryContent.replace(
|
|
205
|
+
/\/\/# sourceMappingURL=index\.js\.map/,
|
|
206
|
+
`//# sourceMappingURL=${hashedMapName2}`
|
|
207
|
+
);
|
|
208
|
+
await fs6.writeFile(path.join(outputDir, hashedName2), entryContent);
|
|
209
|
+
await fs6.unlink(indexPath);
|
|
210
|
+
try {
|
|
211
|
+
await fs6.access(indexMapPath);
|
|
212
|
+
await fs6.rename(indexMapPath, path.join(outputDir, hashedMapName2));
|
|
213
|
+
} catch (e2) {
|
|
214
|
+
}
|
|
215
|
+
logger.info(`Entry hashed: ${hashedName2}`);
|
|
216
|
+
return;
|
|
40
217
|
}
|
|
41
|
-
|
|
42
|
-
|
|
218
|
+
const hash = crypto.createHash("sha256").update(entryContent).digest("hex").slice(0, 8);
|
|
219
|
+
const hashedName = `bundle-entry-${hash}.js`;
|
|
220
|
+
const hashedMapName = `bundle-entry-${hash}.js.map`;
|
|
221
|
+
entryContent = entryContent.replace(
|
|
222
|
+
/\/\/# sourceMappingURL=bundle-entry\.js\.map/,
|
|
223
|
+
`//# sourceMappingURL=${hashedMapName}`
|
|
224
|
+
);
|
|
225
|
+
await fs6.writeFile(path.join(outputDir, hashedName), entryContent);
|
|
226
|
+
await fs6.unlink(entryPath);
|
|
227
|
+
try {
|
|
228
|
+
await fs6.access(mapPath);
|
|
229
|
+
await fs6.rename(mapPath, path.join(outputDir, hashedMapName));
|
|
230
|
+
} catch (e) {
|
|
43
231
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
232
|
+
logger.info(`Entry hashed: ${hashedName}`);
|
|
233
|
+
}
|
|
234
|
+
async function generateManifest2(themeName, themePath, outputDir) {
|
|
235
|
+
let version = "1.0.0";
|
|
236
|
+
let themeId = themeName;
|
|
237
|
+
try {
|
|
238
|
+
const pkgContent = await fs6.readFile(
|
|
239
|
+
path.join(themePath, "package.json"),
|
|
240
|
+
"utf-8"
|
|
241
|
+
);
|
|
242
|
+
const pkg = JSON.parse(pkgContent);
|
|
243
|
+
version = pkg.version || version;
|
|
244
|
+
if (pkg.name) {
|
|
245
|
+
themeId = pkg.name.replace(/^@onex-themes\//, "");
|
|
50
246
|
}
|
|
51
|
-
|
|
247
|
+
} catch (e) {
|
|
52
248
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
249
|
+
const [sectionFiles, blockFiles, schemaFiles] = await Promise.all([
|
|
250
|
+
glob("sections/**/index.ts", { cwd: themePath }),
|
|
251
|
+
glob("blocks/**/index.ts", { cwd: themePath }),
|
|
252
|
+
glob("**/*.schema.ts", { cwd: themePath })
|
|
253
|
+
]);
|
|
254
|
+
let hasThemeConfig = false;
|
|
255
|
+
try {
|
|
256
|
+
await fs6.access(path.join(themePath, "theme.config.ts"));
|
|
257
|
+
hasThemeConfig = true;
|
|
258
|
+
} catch (e) {
|
|
259
|
+
}
|
|
260
|
+
const allFiles = await glob("**/*", { cwd: outputDir, nodir: true });
|
|
261
|
+
const jsFiles = allFiles.filter((f) => f.endsWith(".js"));
|
|
262
|
+
const cssFiles = allFiles.filter((f) => f.endsWith(".css"));
|
|
263
|
+
const entryFile = jsFiles.find((f) => f.includes("bundle-entry")) || "bundle-entry.js";
|
|
264
|
+
const manifest = {
|
|
265
|
+
themeId,
|
|
266
|
+
version,
|
|
267
|
+
name: themeId.charAt(0).toUpperCase() + themeId.slice(1),
|
|
268
|
+
compiledAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
269
|
+
format: "esm",
|
|
270
|
+
platform: "browser",
|
|
271
|
+
target: "es2020",
|
|
272
|
+
counts: {
|
|
273
|
+
sections: sectionFiles.length,
|
|
274
|
+
blocks: blockFiles.length,
|
|
275
|
+
schemas: schemaFiles.length
|
|
276
|
+
},
|
|
277
|
+
output: {
|
|
278
|
+
entry: entryFile,
|
|
279
|
+
chunks: jsFiles.filter((f) => f !== entryFile && !f.endsWith(".map")),
|
|
280
|
+
assets: allFiles.filter(
|
|
281
|
+
(f) => [".png", ".jpg", ".jpeg", ".svg", ".gif", ".webp"].some(
|
|
282
|
+
(ext) => f.endsWith(ext)
|
|
283
|
+
)
|
|
284
|
+
),
|
|
285
|
+
stylesheets: cssFiles
|
|
286
|
+
},
|
|
287
|
+
external: ["react", "react-dom", "@onexapis/core"],
|
|
288
|
+
source: {
|
|
289
|
+
sections: sectionFiles,
|
|
290
|
+
blocks: blockFiles,
|
|
291
|
+
schemas: schemaFiles,
|
|
292
|
+
hasThemeConfig
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
await fs6.writeFile(
|
|
296
|
+
path.join(outputDir, "manifest.json"),
|
|
297
|
+
JSON.stringify(manifest, null, 2)
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
async function compileStandaloneTheme(themePath, themeName) {
|
|
301
|
+
const outputDir = path.join(themePath, "dist");
|
|
302
|
+
const bundleEntry = path.join(themePath, "bundle-entry.ts");
|
|
303
|
+
const indexEntry = path.join(themePath, "index.ts");
|
|
304
|
+
let entryPoint = indexEntry;
|
|
305
|
+
try {
|
|
306
|
+
await fs6.access(bundleEntry);
|
|
307
|
+
entryPoint = bundleEntry;
|
|
308
|
+
} catch (e) {
|
|
309
|
+
}
|
|
310
|
+
const shimPath = path.join(outputDir, ".process-shim.js");
|
|
311
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
312
|
+
await fs6.writeFile(shimPath, PROCESS_SHIM);
|
|
313
|
+
const buildOptions = {
|
|
314
|
+
entryPoints: [entryPoint],
|
|
315
|
+
bundle: true,
|
|
316
|
+
platform: "browser",
|
|
317
|
+
format: "esm",
|
|
318
|
+
outdir: outputDir,
|
|
319
|
+
splitting: false,
|
|
320
|
+
chunkNames: "[name]-[hash]",
|
|
321
|
+
banner: {
|
|
322
|
+
js: '"use client";'
|
|
323
|
+
},
|
|
324
|
+
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath)],
|
|
325
|
+
external: [],
|
|
326
|
+
alias: {
|
|
327
|
+
events: "events/",
|
|
328
|
+
buffer: "buffer/"
|
|
329
|
+
},
|
|
330
|
+
inject: [shimPath],
|
|
331
|
+
define: {
|
|
332
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
333
|
+
global: "globalThis"
|
|
334
|
+
},
|
|
335
|
+
minify: true,
|
|
336
|
+
sourcemap: true,
|
|
337
|
+
logLevel: "warning",
|
|
338
|
+
target: "es2020",
|
|
339
|
+
jsx: "automatic",
|
|
340
|
+
jsxImportSource: "react",
|
|
341
|
+
loader: {
|
|
342
|
+
".tsx": "tsx",
|
|
343
|
+
".ts": "ts",
|
|
344
|
+
".jpg": "file",
|
|
345
|
+
".jpeg": "file",
|
|
346
|
+
".png": "file",
|
|
347
|
+
".gif": "file",
|
|
348
|
+
".svg": "file",
|
|
349
|
+
".webp": "file"
|
|
350
|
+
},
|
|
351
|
+
assetNames: "assets/[name]-[hash]",
|
|
352
|
+
publicPath: "./",
|
|
353
|
+
metafile: true
|
|
354
|
+
};
|
|
355
|
+
try {
|
|
356
|
+
const result = await esbuild.build(buildOptions);
|
|
357
|
+
try {
|
|
358
|
+
await fs6.unlink(shimPath);
|
|
359
|
+
} catch (e) {
|
|
360
|
+
}
|
|
361
|
+
await contentHashEntry(outputDir);
|
|
362
|
+
await generateManifest2(themeName, themePath, outputDir);
|
|
363
|
+
if (result.metafile) {
|
|
364
|
+
const outputs = result.metafile.outputs;
|
|
365
|
+
let totalSize = 0;
|
|
366
|
+
for (const output of Object.values(outputs)) {
|
|
367
|
+
totalSize += output.bytes;
|
|
368
|
+
}
|
|
369
|
+
const totalKB = (totalSize / 1024).toFixed(2);
|
|
370
|
+
logger.info(`Bundle size: ${totalKB} KB`);
|
|
56
371
|
}
|
|
372
|
+
return true;
|
|
373
|
+
} catch (error) {
|
|
374
|
+
try {
|
|
375
|
+
await fs6.unlink(shimPath);
|
|
376
|
+
} catch (e) {
|
|
377
|
+
}
|
|
378
|
+
logger.error(`esbuild compilation failed: ${error}`);
|
|
379
|
+
return false;
|
|
57
380
|
}
|
|
58
|
-
|
|
59
|
-
|
|
381
|
+
}
|
|
382
|
+
async function compileStandaloneThemeDev(themePath, themeName) {
|
|
383
|
+
const outputDir = path.join(themePath, "dist");
|
|
384
|
+
const bundleEntry = path.join(themePath, "bundle-entry.ts");
|
|
385
|
+
const indexEntry = path.join(themePath, "index.ts");
|
|
386
|
+
let entryPoint = indexEntry;
|
|
387
|
+
try {
|
|
388
|
+
await fs6.access(bundleEntry);
|
|
389
|
+
entryPoint = bundleEntry;
|
|
390
|
+
} catch (e) {
|
|
391
|
+
}
|
|
392
|
+
const shimPath = path.join(outputDir, ".process-shim.js");
|
|
393
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
394
|
+
await fs6.writeFile(shimPath, PROCESS_SHIM);
|
|
395
|
+
const buildOptions = {
|
|
396
|
+
entryPoints: [entryPoint],
|
|
397
|
+
bundle: true,
|
|
398
|
+
platform: "browser",
|
|
399
|
+
format: "esm",
|
|
400
|
+
outdir: outputDir,
|
|
401
|
+
splitting: false,
|
|
402
|
+
banner: {
|
|
403
|
+
js: '"use client";'
|
|
404
|
+
},
|
|
405
|
+
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath)],
|
|
406
|
+
external: [],
|
|
407
|
+
alias: {
|
|
408
|
+
events: "events/",
|
|
409
|
+
buffer: "buffer/"
|
|
410
|
+
},
|
|
411
|
+
inject: [shimPath],
|
|
412
|
+
define: {
|
|
413
|
+
"process.env.NODE_ENV": JSON.stringify("development"),
|
|
414
|
+
global: "globalThis"
|
|
415
|
+
},
|
|
416
|
+
minify: false,
|
|
417
|
+
sourcemap: true,
|
|
418
|
+
logLevel: "warning",
|
|
419
|
+
target: "es2020",
|
|
420
|
+
jsx: "automatic",
|
|
421
|
+
jsxImportSource: "react",
|
|
422
|
+
loader: {
|
|
423
|
+
".tsx": "tsx",
|
|
424
|
+
".ts": "ts",
|
|
425
|
+
".jpg": "file",
|
|
426
|
+
".jpeg": "file",
|
|
427
|
+
".png": "file",
|
|
428
|
+
".gif": "file",
|
|
429
|
+
".svg": "file",
|
|
430
|
+
".webp": "file"
|
|
431
|
+
},
|
|
432
|
+
assetNames: "assets/[name]-[hash]",
|
|
433
|
+
publicPath: "./",
|
|
434
|
+
metafile: true
|
|
435
|
+
};
|
|
436
|
+
const context2 = await esbuild.context(buildOptions);
|
|
437
|
+
await context2.rebuild();
|
|
438
|
+
await generateManifest2(themeName, themePath, outputDir);
|
|
439
|
+
return { context: context2, outputDir };
|
|
440
|
+
}
|
|
441
|
+
async function compilePreviewRuntime(themePath) {
|
|
442
|
+
const outputDir = path.join(themePath, "dist");
|
|
443
|
+
await fs6.mkdir(outputDir, { recursive: true });
|
|
444
|
+
const outputPath = path.join(outputDir, "preview-runtime.js");
|
|
445
|
+
const locations = [
|
|
446
|
+
path.join(__dirname, "..", "preview", "preview-app.tsx"),
|
|
447
|
+
path.join(__dirname, "preview", "preview-app.tsx"),
|
|
448
|
+
path.join(__dirname, "..", "..", "src", "preview", "preview-app.tsx")
|
|
449
|
+
];
|
|
450
|
+
let previewEntryPath = null;
|
|
451
|
+
for (const loc of locations) {
|
|
452
|
+
try {
|
|
453
|
+
await fs6.access(loc);
|
|
454
|
+
previewEntryPath = loc;
|
|
455
|
+
break;
|
|
456
|
+
} catch (e) {
|
|
457
|
+
}
|
|
60
458
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
459
|
+
if (!previewEntryPath) {
|
|
460
|
+
throw new Error(
|
|
461
|
+
`Preview app source not found. Searched:
|
|
462
|
+
${locations.join("\n")}`
|
|
463
|
+
);
|
|
66
464
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
465
|
+
const serverStubPlugin = {
|
|
466
|
+
name: "server-stub",
|
|
467
|
+
setup(build2) {
|
|
468
|
+
build2.onResolve({ filter: /^server-only$/ }, () => ({
|
|
469
|
+
path: "server-only",
|
|
470
|
+
namespace: "server-stub"
|
|
471
|
+
}));
|
|
472
|
+
build2.onLoad({ filter: /.*/, namespace: "server-stub" }, () => ({
|
|
473
|
+
contents: "// server-only stub for browser",
|
|
474
|
+
loader: "js"
|
|
475
|
+
}));
|
|
476
|
+
const nodeBuiltins = [
|
|
477
|
+
"fs",
|
|
478
|
+
"fs/promises",
|
|
479
|
+
"path",
|
|
480
|
+
"os",
|
|
481
|
+
"crypto",
|
|
482
|
+
"stream",
|
|
483
|
+
"url",
|
|
484
|
+
"http",
|
|
485
|
+
"https",
|
|
486
|
+
"net",
|
|
487
|
+
"tls",
|
|
488
|
+
"child_process",
|
|
489
|
+
"util",
|
|
490
|
+
"events",
|
|
491
|
+
"buffer",
|
|
492
|
+
"querystring",
|
|
493
|
+
"zlib"
|
|
494
|
+
];
|
|
495
|
+
for (const mod of nodeBuiltins) {
|
|
496
|
+
build2.onResolve({ filter: new RegExp(`^${mod.replace("/", "\\/")}$`) }, () => ({
|
|
497
|
+
path: mod,
|
|
498
|
+
namespace: "node-stub"
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
build2.onLoad({ filter: /.*/, namespace: "node-stub" }, (args) => {
|
|
502
|
+
const stubs = {
|
|
503
|
+
events: "export class EventEmitter { on(){return this} off(){return this} emit(){return false} addListener(){return this} removeListener(){return this} } export default { EventEmitter };",
|
|
504
|
+
path: "export function join(){return ''} export function resolve(){return ''} export function dirname(){return ''} export function basename(){return ''} export function extname(){return ''} export default {};",
|
|
505
|
+
fs: "export const promises = {}; export function readFileSync(){return ''} export function existsSync(){return false} export default {};"
|
|
506
|
+
};
|
|
507
|
+
return {
|
|
508
|
+
contents: stubs[args.path] || "export default {};",
|
|
509
|
+
loader: "js"
|
|
510
|
+
};
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
await esbuild.build({
|
|
515
|
+
entryPoints: [previewEntryPath],
|
|
516
|
+
bundle: true,
|
|
517
|
+
platform: "browser",
|
|
518
|
+
format: "esm",
|
|
519
|
+
outfile: outputPath,
|
|
520
|
+
// Bundle React + core INTO the output (NOT externalized)
|
|
521
|
+
external: [],
|
|
522
|
+
plugins: [serverStubPlugin],
|
|
523
|
+
minify: false,
|
|
524
|
+
sourcemap: true,
|
|
525
|
+
target: "es2020",
|
|
526
|
+
jsx: "automatic",
|
|
527
|
+
jsxImportSource: "react",
|
|
528
|
+
define: {
|
|
529
|
+
"process.env.NODE_ENV": JSON.stringify("development"),
|
|
530
|
+
global: "globalThis"
|
|
531
|
+
},
|
|
532
|
+
loader: { ".tsx": "tsx", ".ts": "ts" },
|
|
533
|
+
// Force CJS resolution to avoid sideEffects:false dropping ESM chunk imports
|
|
534
|
+
conditions: ["require", "default"],
|
|
535
|
+
mainFields: ["main"],
|
|
536
|
+
logOverride: {
|
|
537
|
+
"ignored-bare-import": "silent"
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
return outputPath;
|
|
541
|
+
}
|
|
542
|
+
var PROCESS_SHIM, reactGlobalPlugin;
|
|
543
|
+
var init_compile_theme = __esm({
|
|
544
|
+
"src/utils/compile-theme.ts"() {
|
|
545
|
+
init_logger();
|
|
546
|
+
PROCESS_SHIM = `
|
|
547
|
+
if (typeof process === "undefined") {
|
|
548
|
+
globalThis.process = {
|
|
549
|
+
env: {},
|
|
550
|
+
browser: true,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
`;
|
|
554
|
+
reactGlobalPlugin = {
|
|
555
|
+
name: "react-global",
|
|
556
|
+
setup(build2) {
|
|
557
|
+
build2.onResolve({ filter: /^react$/ }, () => ({
|
|
558
|
+
path: "react-external",
|
|
559
|
+
namespace: "react-global"
|
|
560
|
+
}));
|
|
561
|
+
build2.onResolve({ filter: /^react-dom$/ }, () => ({
|
|
562
|
+
path: "react-dom-external",
|
|
563
|
+
namespace: "react-global"
|
|
564
|
+
}));
|
|
565
|
+
build2.onResolve({ filter: /^react\/jsx-runtime$/ }, () => ({
|
|
566
|
+
path: "react-jsx-runtime-external",
|
|
567
|
+
namespace: "react-global"
|
|
568
|
+
}));
|
|
569
|
+
build2.onLoad({ filter: /.*/, namespace: "react-global" }, (args) => {
|
|
570
|
+
if (args.path === "react-external") {
|
|
571
|
+
return {
|
|
572
|
+
contents: `
|
|
573
|
+
if (!globalThis.__ONEX_REACT__) {
|
|
574
|
+
throw new Error('[Theme Bundle] React not initialized. Ensure globalThis.__ONEX_REACT__ is set before loading theme.');
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const React = globalThis.__ONEX_REACT__;
|
|
578
|
+
export default React;
|
|
579
|
+
|
|
580
|
+
export const {
|
|
581
|
+
useState,
|
|
582
|
+
useEffect,
|
|
583
|
+
useContext,
|
|
584
|
+
useReducer,
|
|
585
|
+
useCallback,
|
|
586
|
+
useMemo,
|
|
587
|
+
useRef,
|
|
588
|
+
useImperativeHandle,
|
|
589
|
+
useLayoutEffect,
|
|
590
|
+
useDebugValue,
|
|
591
|
+
useDeferredValue,
|
|
592
|
+
useTransition,
|
|
593
|
+
useId,
|
|
594
|
+
useSyncExternalStore,
|
|
595
|
+
useInsertionEffect,
|
|
596
|
+
createContext,
|
|
597
|
+
forwardRef,
|
|
598
|
+
lazy,
|
|
599
|
+
memo,
|
|
600
|
+
startTransition,
|
|
601
|
+
createElement,
|
|
602
|
+
cloneElement,
|
|
603
|
+
isValidElement,
|
|
604
|
+
Children,
|
|
605
|
+
Fragment,
|
|
606
|
+
Profiler,
|
|
607
|
+
StrictMode,
|
|
608
|
+
Suspense,
|
|
609
|
+
Component,
|
|
610
|
+
PureComponent,
|
|
611
|
+
useActionState,
|
|
612
|
+
use,
|
|
613
|
+
} = React;
|
|
614
|
+
`.trim(),
|
|
615
|
+
loader: "js"
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
if (args.path === "react-dom-external") {
|
|
619
|
+
return {
|
|
620
|
+
contents: `
|
|
621
|
+
if (!globalThis.__ONEX_REACT_DOM__) {
|
|
622
|
+
throw new Error('[Theme Bundle] ReactDOM not initialized. Ensure globalThis.__ONEX_REACT_DOM__ is set before loading theme.');
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const ReactDOM = globalThis.__ONEX_REACT_DOM__;
|
|
626
|
+
export default ReactDOM;
|
|
627
|
+
|
|
628
|
+
export const {
|
|
629
|
+
createRoot,
|
|
630
|
+
hydrateRoot,
|
|
631
|
+
flushSync,
|
|
632
|
+
createPortal,
|
|
633
|
+
findDOMNode,
|
|
634
|
+
render,
|
|
635
|
+
hydrate,
|
|
636
|
+
unmountComponentAtNode,
|
|
637
|
+
} = ReactDOM;
|
|
638
|
+
`.trim(),
|
|
639
|
+
loader: "js"
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
if (args.path === "react-jsx-runtime-external") {
|
|
643
|
+
return {
|
|
644
|
+
contents: `
|
|
645
|
+
if (!globalThis.__ONEX_JSX_RUNTIME__) {
|
|
646
|
+
throw new Error('[Theme Bundle] React JSX runtime not initialized. Ensure globalThis.__ONEX_JSX_RUNTIME__ is set before loading theme.');
|
|
647
|
+
}
|
|
648
|
+
const _jsxRuntime = globalThis.__ONEX_JSX_RUNTIME__;
|
|
649
|
+
export const jsx = _jsxRuntime.jsx;
|
|
650
|
+
export const jsxs = _jsxRuntime.jsxs;
|
|
651
|
+
export const Fragment = _jsxRuntime.Fragment;
|
|
652
|
+
`.trim(),
|
|
653
|
+
loader: "js"
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
return null;
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
};
|
|
70
660
|
}
|
|
71
|
-
};
|
|
72
|
-
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
// src/commands/init.ts
|
|
664
|
+
init_logger();
|
|
73
665
|
|
|
74
666
|
// src/utils/validators.ts
|
|
75
667
|
function validateName(name) {
|
|
@@ -89,8 +681,8 @@ function validateThemeName(name) {
|
|
|
89
681
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
90
682
|
}
|
|
91
683
|
function pathExists(filePath) {
|
|
92
|
-
const
|
|
93
|
-
return
|
|
684
|
+
const fs11 = __require("fs-extra");
|
|
685
|
+
return fs11.existsSync(filePath);
|
|
94
686
|
}
|
|
95
687
|
function validateCategory(category) {
|
|
96
688
|
const validCategories = [
|
|
@@ -123,6 +715,9 @@ function getValidCategories() {
|
|
|
123
715
|
"contact"
|
|
124
716
|
];
|
|
125
717
|
}
|
|
718
|
+
|
|
719
|
+
// src/utils/file-helpers.ts
|
|
720
|
+
init_logger();
|
|
126
721
|
async function renderTemplate(templatePath, data) {
|
|
127
722
|
const template = await fs.readFile(templatePath, "utf-8");
|
|
128
723
|
return ejs.render(template, data);
|
|
@@ -208,18 +803,18 @@ function getProjectRoot() {
|
|
|
208
803
|
}
|
|
209
804
|
function getThemesDir() {
|
|
210
805
|
const root = getProjectRoot();
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return path.
|
|
806
|
+
if (fs.existsSync(path.join(root, "themes")))
|
|
807
|
+
return path.join(root, "themes");
|
|
808
|
+
if (fs.existsSync(path.join(root, "src/themes")))
|
|
809
|
+
return path.join(root, "src/themes");
|
|
810
|
+
return path.dirname(root);
|
|
216
811
|
}
|
|
217
812
|
function getFeaturesDir() {
|
|
218
813
|
return path.join(getProjectRoot(), "src/features");
|
|
219
814
|
}
|
|
220
815
|
function isOneXProject() {
|
|
221
816
|
const root = getProjectRoot();
|
|
222
|
-
return fs.existsSync(path.join(root, "themes")) || fs.existsSync(path.join(root, "src/themes"));
|
|
817
|
+
return fs.existsSync(path.join(root, "themes")) || fs.existsSync(path.join(root, "src/themes")) || fs.existsSync(path.join(root, "theme.config.ts")) || fs.existsSync(path.join(root, "bundle-entry.ts"));
|
|
223
818
|
}
|
|
224
819
|
function ensureOneXProject() {
|
|
225
820
|
if (!isOneXProject()) {
|
|
@@ -681,9 +1276,20 @@ export const homePageConfig: PageConfig = {
|
|
|
681
1276
|
};
|
|
682
1277
|
`;
|
|
683
1278
|
}
|
|
1279
|
+
|
|
1280
|
+
// src/commands/create-section.ts
|
|
1281
|
+
init_logger();
|
|
684
1282
|
async function createSectionCommand(name, options) {
|
|
685
1283
|
logger.header("Create New Section");
|
|
686
1284
|
ensureOneXProject();
|
|
1285
|
+
if (!options.theme) {
|
|
1286
|
+
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
1287
|
+
(f) => fs.existsSync(path.join(process.cwd(), f))
|
|
1288
|
+
);
|
|
1289
|
+
if (isStandaloneTheme) {
|
|
1290
|
+
options.theme = path.basename(process.cwd());
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
687
1293
|
const sectionName = toKebabCase(name);
|
|
688
1294
|
if (!validateName(sectionName)) {
|
|
689
1295
|
logger.error(
|
|
@@ -912,9 +1518,20 @@ export { ${data.sectionName}Schema } from "./${data.sectionName}.schema";
|
|
|
912
1518
|
${hasTemplate ? `export { ${data.sectionNamePascal}Default } from "./${data.sectionName}-default";` : ""}
|
|
913
1519
|
`;
|
|
914
1520
|
}
|
|
1521
|
+
|
|
1522
|
+
// src/commands/create-block.ts
|
|
1523
|
+
init_logger();
|
|
915
1524
|
async function createBlockCommand(name, options) {
|
|
916
1525
|
logger.header("Create New Block");
|
|
917
1526
|
ensureOneXProject();
|
|
1527
|
+
if (!options.theme) {
|
|
1528
|
+
const isStandaloneTheme = ["theme.config.ts", "bundle-entry.ts"].some(
|
|
1529
|
+
(f) => fs.existsSync(path.join(process.cwd(), f))
|
|
1530
|
+
);
|
|
1531
|
+
if (isStandaloneTheme) {
|
|
1532
|
+
options.theme = path.basename(process.cwd());
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
918
1535
|
const blockName = toKebabCase(name);
|
|
919
1536
|
if (!validateName(blockName)) {
|
|
920
1537
|
logger.error(
|
|
@@ -1128,6 +1745,9 @@ export { ${data.blockName}Definition } from "./${data.blockName}.schema";
|
|
|
1128
1745
|
export { ${data.blockNamePascal} } from "./${data.blockName}";
|
|
1129
1746
|
`;
|
|
1130
1747
|
}
|
|
1748
|
+
|
|
1749
|
+
// src/commands/create-component.ts
|
|
1750
|
+
init_logger();
|
|
1131
1751
|
async function createComponentCommand(name, options) {
|
|
1132
1752
|
logger.header("Create New Component");
|
|
1133
1753
|
ensureOneXProject();
|
|
@@ -1332,6 +1952,9 @@ export { ${data.componentName}Definition } from "./${data.componentName}.schema"
|
|
|
1332
1952
|
export { ${data.componentNamePascal} } from "./${data.componentName}";
|
|
1333
1953
|
`;
|
|
1334
1954
|
}
|
|
1955
|
+
|
|
1956
|
+
// src/commands/list.ts
|
|
1957
|
+
init_logger();
|
|
1335
1958
|
async function listCommand(options) {
|
|
1336
1959
|
logger.header("OneX Project Inventory");
|
|
1337
1960
|
ensureOneXProject();
|
|
@@ -1463,7 +2086,11 @@ async function listThemesInfo() {
|
|
|
1463
2086
|
}
|
|
1464
2087
|
logger.newLine();
|
|
1465
2088
|
}
|
|
2089
|
+
|
|
2090
|
+
// src/commands/build.ts
|
|
2091
|
+
init_logger();
|
|
1466
2092
|
async function buildCommand(options) {
|
|
2093
|
+
var _a;
|
|
1467
2094
|
logger.header("Build Theme");
|
|
1468
2095
|
let themePath;
|
|
1469
2096
|
let themeName;
|
|
@@ -1484,8 +2111,12 @@ async function buildCommand(options) {
|
|
|
1484
2111
|
process.exit(1);
|
|
1485
2112
|
}
|
|
1486
2113
|
} else {
|
|
1487
|
-
const
|
|
1488
|
-
|
|
2114
|
+
const isThemeDir = [
|
|
2115
|
+
"theme.config.ts",
|
|
2116
|
+
"bundle-entry.ts",
|
|
2117
|
+
"manifest.ts"
|
|
2118
|
+
].some((f) => fs.existsSync(path.join(process.cwd(), f)));
|
|
2119
|
+
if (isThemeDir) {
|
|
1489
2120
|
themePath = process.cwd();
|
|
1490
2121
|
themeName = path.basename(themePath);
|
|
1491
2122
|
logger.info(`Building current theme: ${themeName}`);
|
|
@@ -1528,11 +2159,20 @@ async function buildCommand(options) {
|
|
|
1528
2159
|
process.exit(1);
|
|
1529
2160
|
}
|
|
1530
2161
|
logger.stopSpinner(true, "Lint passed");
|
|
1531
|
-
const
|
|
2162
|
+
const pkgJson = fs.readJsonSync(packageJsonPath);
|
|
2163
|
+
const buildScript = ((_a = pkgJson.scripts) == null ? void 0 : _a.build) || "";
|
|
2164
|
+
const isRecursive = buildScript.includes("onex build") || buildScript.includes("onex-cli build");
|
|
1532
2165
|
logger.startSpinner(
|
|
1533
2166
|
options.watch ? "Building (watch mode)..." : "Building..."
|
|
1534
2167
|
);
|
|
1535
|
-
|
|
2168
|
+
let buildSuccess;
|
|
2169
|
+
if (isRecursive) {
|
|
2170
|
+
const { compileStandaloneTheme: compileStandaloneTheme2 } = await Promise.resolve().then(() => (init_compile_theme(), compile_theme_exports));
|
|
2171
|
+
buildSuccess = await compileStandaloneTheme2(themePath, themeName);
|
|
2172
|
+
} else {
|
|
2173
|
+
const buildArgs = options.watch ? ["build", "--watch"] : ["build"];
|
|
2174
|
+
buildSuccess = await runCommand("pnpm", buildArgs, themePath);
|
|
2175
|
+
}
|
|
1536
2176
|
if (!buildSuccess && !options.watch) {
|
|
1537
2177
|
logger.stopSpinner(false, "Build failed");
|
|
1538
2178
|
process.exit(1);
|
|
@@ -1573,6 +2213,9 @@ function runCommand(command, args, cwd) {
|
|
|
1573
2213
|
});
|
|
1574
2214
|
});
|
|
1575
2215
|
}
|
|
2216
|
+
|
|
2217
|
+
// src/commands/upload.ts
|
|
2218
|
+
init_logger();
|
|
1576
2219
|
function getS3Client() {
|
|
1577
2220
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
1578
2221
|
if (adapterMode === "vps") {
|
|
@@ -1612,21 +2255,12 @@ function getBucketName(env) {
|
|
|
1612
2255
|
return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
|
|
1613
2256
|
}
|
|
1614
2257
|
async function findCompiledThemeDir(themeId, version) {
|
|
1615
|
-
const searchPaths = [
|
|
1616
|
-
path.resolve(process.cwd(), "dist"),
|
|
1617
|
-
path.resolve(
|
|
1618
|
-
process.cwd(),
|
|
1619
|
-
`../../apps/api-server/compiled-themes/${themeId}@${version}`
|
|
1620
|
-
),
|
|
1621
|
-
path.resolve(
|
|
1622
|
-
process.cwd(),
|
|
1623
|
-
`../api-server/compiled-themes/${themeId}@${version}`
|
|
1624
|
-
)
|
|
1625
|
-
];
|
|
2258
|
+
const searchPaths = [path.resolve(process.cwd(), "dist")];
|
|
1626
2259
|
for (const dir of searchPaths) {
|
|
1627
2260
|
if (await fs.pathExists(dir)) {
|
|
1628
|
-
const
|
|
1629
|
-
|
|
2261
|
+
const hasManifest = await fs.pathExists(path.join(dir, "manifest.json"));
|
|
2262
|
+
const hasThemeEntry = await fs.pathExists(path.join(dir, "bundle-entry.js")) || await fs.pathExists(path.join(dir, "theme.config.js")) || await fs.pathExists(path.join(dir, "index.js"));
|
|
2263
|
+
if (hasManifest || hasThemeEntry) {
|
|
1630
2264
|
return dir;
|
|
1631
2265
|
}
|
|
1632
2266
|
}
|
|
@@ -1729,13 +2363,8 @@ async function uploadCommand(options) {
|
|
|
1729
2363
|
`Compiled theme not found for ${themeId}@${version}. Run 'onex build' first.`
|
|
1730
2364
|
)
|
|
1731
2365
|
);
|
|
1732
|
-
logger.info(
|
|
1733
|
-
|
|
1734
|
-
`Expected locations:
|
|
1735
|
-
- ./dist/
|
|
1736
|
-
- ../../apps/api-server/compiled-themes/${themeId}@${version}/`
|
|
1737
|
-
)
|
|
1738
|
-
);
|
|
2366
|
+
logger.info(chalk4.gray(`Expected location:
|
|
2367
|
+
- ./dist/`));
|
|
1739
2368
|
process.exit(1);
|
|
1740
2369
|
}
|
|
1741
2370
|
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
@@ -1842,9 +2471,7 @@ async function uploadCommand(options) {
|
|
|
1842
2471
|
);
|
|
1843
2472
|
console.log(chalk4.cyan(" Bucket: ") + chalk4.white(bucket));
|
|
1844
2473
|
console.log(
|
|
1845
|
-
chalk4.cyan(" Files: ") + chalk4.white(
|
|
1846
|
-
`bundle.zip${sourceUploaded ? " + source.zip" : ""}`
|
|
1847
|
-
)
|
|
2474
|
+
chalk4.cyan(" Files: ") + chalk4.white(`bundle.zip${sourceUploaded ? " + source.zip" : ""}`)
|
|
1848
2475
|
);
|
|
1849
2476
|
console.log(
|
|
1850
2477
|
chalk4.cyan(" Path: ") + chalk4.gray(`s3://${bucket}/themes/${themeId}/${version}/`)
|
|
@@ -1856,6 +2483,9 @@ async function uploadCommand(options) {
|
|
|
1856
2483
|
process.exit(1);
|
|
1857
2484
|
}
|
|
1858
2485
|
}
|
|
2486
|
+
|
|
2487
|
+
// src/commands/download.ts
|
|
2488
|
+
init_logger();
|
|
1859
2489
|
function getS3Client2() {
|
|
1860
2490
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
1861
2491
|
if (adapterMode === "vps") {
|
|
@@ -2003,11 +2633,7 @@ function showDownloadFailureHelp(themeId, bucket) {
|
|
|
2003
2633
|
);
|
|
2004
2634
|
console.log();
|
|
2005
2635
|
console.log(chalk4.white("4. Verify theme exists in S3:"));
|
|
2006
|
-
console.log(
|
|
2007
|
-
chalk4.gray(
|
|
2008
|
-
` aws s3 ls s3://${bucket}/themes/${themeId}/`
|
|
2009
|
-
)
|
|
2010
|
-
);
|
|
2636
|
+
console.log(chalk4.gray(` aws s3 ls s3://${bucket}/themes/${themeId}/`));
|
|
2011
2637
|
console.log();
|
|
2012
2638
|
}
|
|
2013
2639
|
async function downloadCommand(options) {
|
|
@@ -2083,6 +2709,9 @@ async function downloadCommand(options) {
|
|
|
2083
2709
|
process.exit(1);
|
|
2084
2710
|
}
|
|
2085
2711
|
}
|
|
2712
|
+
|
|
2713
|
+
// src/commands/clone.ts
|
|
2714
|
+
init_logger();
|
|
2086
2715
|
function getS3Client3() {
|
|
2087
2716
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
2088
2717
|
if (adapterMode === "vps") {
|
|
@@ -2186,17 +2815,100 @@ function runInstall(cwd) {
|
|
|
2186
2815
|
proc.on("error", () => resolve(false));
|
|
2187
2816
|
});
|
|
2188
2817
|
}
|
|
2818
|
+
async function promptThemeName(originalName) {
|
|
2819
|
+
const { default: inquirer5 } = await import('inquirer');
|
|
2820
|
+
const { themeName } = await inquirer5.prompt([
|
|
2821
|
+
{
|
|
2822
|
+
type: "input",
|
|
2823
|
+
name: "themeName",
|
|
2824
|
+
message: "New theme name (kebab-case):",
|
|
2825
|
+
default: `my-${originalName}`,
|
|
2826
|
+
validate: (input) => {
|
|
2827
|
+
if (!/^[a-z][a-z0-9-]*$/.test(input)) {
|
|
2828
|
+
return "Theme name must be kebab-case (lowercase letters, numbers, hyphens)";
|
|
2829
|
+
}
|
|
2830
|
+
if (input === originalName) {
|
|
2831
|
+
return `Name must differ from the original theme "${originalName}"`;
|
|
2832
|
+
}
|
|
2833
|
+
return true;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
]);
|
|
2837
|
+
return themeName;
|
|
2838
|
+
}
|
|
2839
|
+
async function renameTheme(themeDir, oldName, newName) {
|
|
2840
|
+
const oldPrefix = `${oldName}-`;
|
|
2841
|
+
const newPrefix = `${newName}-`;
|
|
2842
|
+
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2843
|
+
const pkgPath = path.join(themeDir, "package.json");
|
|
2844
|
+
if (await fs.pathExists(pkgPath)) {
|
|
2845
|
+
const pkg = await fs.readJson(pkgPath);
|
|
2846
|
+
pkg.name = `@onex-themes/${newName}`;
|
|
2847
|
+
if (pkg.description) {
|
|
2848
|
+
pkg.description = pkg.description.replace(
|
|
2849
|
+
new RegExp(oldName, "gi"),
|
|
2850
|
+
newDisplayName
|
|
2851
|
+
);
|
|
2852
|
+
}
|
|
2853
|
+
pkg.version = "1.0.0";
|
|
2854
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
2855
|
+
}
|
|
2856
|
+
const configPath = path.join(themeDir, "theme.config.ts");
|
|
2857
|
+
if (await fs.pathExists(configPath)) {
|
|
2858
|
+
let content = await fs.readFile(configPath, "utf-8");
|
|
2859
|
+
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
2860
|
+
content = content.replace(
|
|
2861
|
+
/name:\s*"[^"]*Theme"/,
|
|
2862
|
+
`name: "${newDisplayName} Theme"`
|
|
2863
|
+
);
|
|
2864
|
+
await fs.writeFile(configPath, content);
|
|
2865
|
+
}
|
|
2866
|
+
const layoutPath = path.join(themeDir, "theme.layout.ts");
|
|
2867
|
+
if (await fs.pathExists(layoutPath)) {
|
|
2868
|
+
let content = await fs.readFile(layoutPath, "utf-8");
|
|
2869
|
+
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
2870
|
+
content = content.replace(
|
|
2871
|
+
/name:\s*"[^"]*Theme"/,
|
|
2872
|
+
`name: "${newDisplayName} Theme"`
|
|
2873
|
+
);
|
|
2874
|
+
await fs.writeFile(layoutPath, content);
|
|
2875
|
+
}
|
|
2876
|
+
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2877
|
+
const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
2878
|
+
for (const file of tsFiles) {
|
|
2879
|
+
const filePath = path.join(themeDir, file);
|
|
2880
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
2881
|
+
const original = content;
|
|
2882
|
+
content = content.replace(
|
|
2883
|
+
new RegExp(`"${oldPrefix}`, "g"),
|
|
2884
|
+
`"${newPrefix}`
|
|
2885
|
+
);
|
|
2886
|
+
content = content.replace(
|
|
2887
|
+
new RegExp(`themeId:\\s*"${oldName}"`, "g"),
|
|
2888
|
+
`themeId: "${newName}"`
|
|
2889
|
+
);
|
|
2890
|
+
content = content.replace(
|
|
2891
|
+
new RegExp(`${oldDisplayName} Theme`, "g"),
|
|
2892
|
+
`${newDisplayName} Theme`
|
|
2893
|
+
);
|
|
2894
|
+
if (content !== original) {
|
|
2895
|
+
await fs.writeFile(filePath, content);
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2189
2899
|
async function cloneCommand(themeName, options) {
|
|
2190
2900
|
logger.header("Clone Theme Source");
|
|
2901
|
+
let newName = options.name;
|
|
2902
|
+
if (!newName) {
|
|
2903
|
+
newName = await promptThemeName(themeName);
|
|
2904
|
+
}
|
|
2191
2905
|
const spinner = ora("Initializing clone...").start();
|
|
2192
2906
|
try {
|
|
2193
2907
|
const bucket = options.bucket || getBucketName3(options.environment);
|
|
2194
|
-
const outputDir = options.output || path.resolve(process.cwd(),
|
|
2908
|
+
const outputDir = options.output || path.resolve(process.cwd(), newName);
|
|
2195
2909
|
const s3Client = getS3Client3();
|
|
2196
2910
|
if (await fs.pathExists(outputDir)) {
|
|
2197
|
-
spinner.fail(
|
|
2198
|
-
chalk4.red(`Directory already exists: ${outputDir}`)
|
|
2199
|
-
);
|
|
2911
|
+
spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
|
|
2200
2912
|
logger.info(
|
|
2201
2913
|
chalk4.gray(
|
|
2202
2914
|
"Use -o to specify a different output directory, or remove the existing directory."
|
|
@@ -2210,9 +2922,7 @@ async function cloneCommand(themeName, options) {
|
|
|
2210
2922
|
version = await resolveLatestVersion2(s3Client, bucket, themeName);
|
|
2211
2923
|
spinner.succeed(`Resolved latest version: ${chalk4.cyan(version)}`);
|
|
2212
2924
|
}
|
|
2213
|
-
spinner.start(
|
|
2214
|
-
`Downloading source.zip for ${themeName}@${version}...`
|
|
2215
|
-
);
|
|
2925
|
+
spinner.start(`Downloading source.zip for ${themeName}@${version}...`);
|
|
2216
2926
|
const s3Key = `themes/${themeName}/${version}/source.zip`;
|
|
2217
2927
|
let zipBuffer;
|
|
2218
2928
|
try {
|
|
@@ -2230,9 +2940,7 @@ async function cloneCommand(themeName, options) {
|
|
|
2230
2940
|
chalk4.yellow("The theme source may not have been uploaded yet.")
|
|
2231
2941
|
);
|
|
2232
2942
|
console.log(
|
|
2233
|
-
chalk4.gray(
|
|
2234
|
-
`Upload source with: onex upload --theme ${themeName}`
|
|
2235
|
-
)
|
|
2943
|
+
chalk4.gray(`Upload source with: onex upload --theme ${themeName}`)
|
|
2236
2944
|
);
|
|
2237
2945
|
console.log();
|
|
2238
2946
|
process.exit(1);
|
|
@@ -2245,6 +2953,13 @@ async function cloneCommand(themeName, options) {
|
|
|
2245
2953
|
zip.extractAllTo(outputDir, true);
|
|
2246
2954
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
2247
2955
|
spinner.succeed(`Extracted ${entries.length} files`);
|
|
2956
|
+
spinner.start(
|
|
2957
|
+
`Renaming theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}...`
|
|
2958
|
+
);
|
|
2959
|
+
await renameTheme(outputDir, themeName, newName);
|
|
2960
|
+
spinner.succeed(
|
|
2961
|
+
`Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
|
|
2962
|
+
);
|
|
2248
2963
|
if (options.install !== false) {
|
|
2249
2964
|
const hasPkgJson = await fs.pathExists(
|
|
2250
2965
|
path.join(outputDir, "package.json")
|
|
@@ -2267,15 +2982,14 @@ async function cloneCommand(themeName, options) {
|
|
|
2267
2982
|
logger.success(chalk4.green.bold("Theme cloned successfully!"));
|
|
2268
2983
|
console.log();
|
|
2269
2984
|
console.log(
|
|
2270
|
-
chalk4.cyan("
|
|
2985
|
+
chalk4.cyan(" Source: ") + chalk4.gray(`${themeName}@${version}`)
|
|
2271
2986
|
);
|
|
2987
|
+
console.log(chalk4.cyan(" Theme: ") + chalk4.white(newName));
|
|
2272
2988
|
console.log(chalk4.cyan(" Location: ") + chalk4.white(outputDir));
|
|
2273
2989
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|
|
2274
2990
|
console.log();
|
|
2275
2991
|
console.log(chalk4.cyan("Next steps:"));
|
|
2276
|
-
console.log(
|
|
2277
|
-
chalk4.gray(` cd ${path.relative(process.cwd(), outputDir)}`)
|
|
2278
|
-
);
|
|
2992
|
+
console.log(chalk4.gray(` cd ${path.relative(process.cwd(), outputDir)}`));
|
|
2279
2993
|
if (options.install === false) {
|
|
2280
2994
|
console.log(chalk4.gray(" pnpm install"));
|
|
2281
2995
|
}
|
|
@@ -2288,6 +3002,9 @@ async function cloneCommand(themeName, options) {
|
|
|
2288
3002
|
}
|
|
2289
3003
|
}
|
|
2290
3004
|
|
|
3005
|
+
// src/index.ts
|
|
3006
|
+
init_logger();
|
|
3007
|
+
|
|
2291
3008
|
export { Logger, buildCommand, cloneCommand, copyTemplate, createBlockCommand, createComponentCommand, createSectionCommand, detectPackageManager, downloadCommand, ensureOneXProject, getFeaturesDir, getProjectRoot, getThemesDir, getValidCategories, initCommand, installDependencies, isOneXProject, listCommand, listThemes, logger, pathExists, renderTemplate, themeExists, toCamelCase, toKebabCase, toPascalCase, uploadCommand, validateCategory, validateName, validateThemeName, writeFile };
|
|
2292
3009
|
//# sourceMappingURL=index.mjs.map
|
|
2293
3010
|
//# sourceMappingURL=index.mjs.map
|