@onexapis/cli 1.0.4 → 1.1.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 +65 -63
- package/dist/cli.js +1150 -105
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +1125 -103
- 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 +1018 -237
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +852 -90
- 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,703 @@ 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) {
|
|
56
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`);
|
|
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
|
+
build2.onResolve({ filter: /^lucide-react/ }, async (args) => {
|
|
513
|
+
var _a;
|
|
514
|
+
if ((_a = args.pluginData) == null ? void 0 : _a.skipStub) return void 0;
|
|
515
|
+
try {
|
|
516
|
+
const result = await build2.resolve(args.path, {
|
|
517
|
+
kind: args.kind,
|
|
518
|
+
resolveDir: args.resolveDir,
|
|
519
|
+
importer: args.importer,
|
|
520
|
+
namespace: "file",
|
|
521
|
+
pluginData: { skipStub: true }
|
|
522
|
+
});
|
|
523
|
+
if (!result.errors.length) return result;
|
|
524
|
+
} catch (e) {
|
|
525
|
+
}
|
|
526
|
+
return { path: args.path, namespace: "lucide-stub" };
|
|
527
|
+
});
|
|
528
|
+
build2.onLoad({ filter: /.*/, namespace: "lucide-stub" }, () => ({
|
|
529
|
+
// Provide all icon names used by @onexapis/core as no-op SVG stub components
|
|
530
|
+
contents: `
|
|
531
|
+
const icon = (props) => null;
|
|
532
|
+
export { icon as Check, icon as ChevronDown, icon as XCircle, icon as AlertTriangle };
|
|
533
|
+
export { icon as CheckCircle, icon as Info, icon as X, icon as XIcon };
|
|
534
|
+
export { icon as CircleIcon, icon as Star, icon as ShoppingCart };
|
|
535
|
+
export { icon as ChevronRight, icon as ChevronLeft, icon as ChevronUp };
|
|
536
|
+
export { icon as Search, icon as Menu, icon as Heart, icon as User };
|
|
537
|
+
export { icon as Trash2, icon as Plus, icon as Minus, icon as Eye, icon as EyeOff };
|
|
538
|
+
export { icon as ArrowRight, icon as ArrowLeft, icon as ExternalLink, icon as Mail };
|
|
539
|
+
export { icon as Phone, icon as MapPin, icon as Calendar, icon as Clock };
|
|
540
|
+
export { icon as Facebook, icon as Twitter, icon as Instagram, icon as Linkedin, icon as Github };
|
|
541
|
+
export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true : icon });
|
|
542
|
+
`.trim(),
|
|
543
|
+
loader: "jsx"
|
|
544
|
+
}));
|
|
545
|
+
build2.onResolve({ filter: /^framer-motion/ }, async (args) => {
|
|
546
|
+
var _a;
|
|
547
|
+
if ((_a = args.pluginData) == null ? void 0 : _a.skipStub) return void 0;
|
|
548
|
+
try {
|
|
549
|
+
const result = await build2.resolve(args.path, {
|
|
550
|
+
kind: args.kind,
|
|
551
|
+
resolveDir: args.resolveDir,
|
|
552
|
+
importer: args.importer,
|
|
553
|
+
namespace: "file",
|
|
554
|
+
pluginData: { skipStub: true }
|
|
555
|
+
});
|
|
556
|
+
if (!result.errors.length) return result;
|
|
557
|
+
} catch (e) {
|
|
558
|
+
}
|
|
559
|
+
return { path: args.path, namespace: "motion-stub" };
|
|
560
|
+
});
|
|
561
|
+
build2.onLoad({ filter: /.*/, namespace: "motion-stub" }, () => ({
|
|
562
|
+
contents: `
|
|
563
|
+
const stub = (props) => props.children || null;
|
|
564
|
+
const handler = { get: (_, name) => name === '__esModule' ? true : stub };
|
|
565
|
+
export const motion = new Proxy({}, handler);
|
|
566
|
+
export const AnimatePresence = stub;
|
|
567
|
+
export default { motion, AnimatePresence };
|
|
568
|
+
`.trim(),
|
|
569
|
+
loader: "jsx"
|
|
570
|
+
}));
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
await esbuild.build({
|
|
574
|
+
entryPoints: [previewEntryPath],
|
|
575
|
+
bundle: true,
|
|
576
|
+
platform: "browser",
|
|
577
|
+
format: "esm",
|
|
578
|
+
outfile: outputPath,
|
|
579
|
+
// Bundle React + core INTO the output (NOT externalized)
|
|
580
|
+
external: [],
|
|
581
|
+
plugins: [serverStubPlugin],
|
|
582
|
+
minify: false,
|
|
583
|
+
sourcemap: true,
|
|
584
|
+
target: "es2020",
|
|
585
|
+
jsx: "automatic",
|
|
586
|
+
jsxImportSource: "react",
|
|
587
|
+
define: {
|
|
588
|
+
"process.env.NODE_ENV": JSON.stringify("development"),
|
|
589
|
+
global: "globalThis"
|
|
590
|
+
},
|
|
591
|
+
loader: { ".tsx": "tsx", ".ts": "ts" },
|
|
592
|
+
// Force CJS resolution to avoid sideEffects:false dropping ESM chunk imports
|
|
593
|
+
conditions: ["require", "default"],
|
|
594
|
+
mainFields: ["main"],
|
|
595
|
+
logOverride: {
|
|
596
|
+
"ignored-bare-import": "silent"
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
return outputPath;
|
|
600
|
+
}
|
|
601
|
+
var PROCESS_SHIM, reactGlobalPlugin;
|
|
602
|
+
var init_compile_theme = __esm({
|
|
603
|
+
"src/utils/compile-theme.ts"() {
|
|
604
|
+
init_logger();
|
|
605
|
+
PROCESS_SHIM = `
|
|
606
|
+
if (typeof process === "undefined") {
|
|
607
|
+
globalThis.process = {
|
|
608
|
+
env: {},
|
|
609
|
+
browser: true,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
`;
|
|
613
|
+
reactGlobalPlugin = {
|
|
614
|
+
name: "react-global",
|
|
615
|
+
setup(build2) {
|
|
616
|
+
build2.onResolve({ filter: /^react$/ }, () => ({
|
|
617
|
+
path: "react-external",
|
|
618
|
+
namespace: "react-global"
|
|
619
|
+
}));
|
|
620
|
+
build2.onResolve({ filter: /^react-dom$/ }, () => ({
|
|
621
|
+
path: "react-dom-external",
|
|
622
|
+
namespace: "react-global"
|
|
623
|
+
}));
|
|
624
|
+
build2.onResolve({ filter: /^react\/jsx-runtime$/ }, () => ({
|
|
625
|
+
path: "react-jsx-runtime-external",
|
|
626
|
+
namespace: "react-global"
|
|
627
|
+
}));
|
|
628
|
+
build2.onLoad({ filter: /.*/, namespace: "react-global" }, (args) => {
|
|
629
|
+
if (args.path === "react-external") {
|
|
630
|
+
return {
|
|
631
|
+
contents: `
|
|
632
|
+
if (!globalThis.__ONEX_REACT__) {
|
|
633
|
+
throw new Error('[Theme Bundle] React not initialized. Ensure globalThis.__ONEX_REACT__ is set before loading theme.');
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const React = globalThis.__ONEX_REACT__;
|
|
637
|
+
export default React;
|
|
638
|
+
|
|
639
|
+
export const {
|
|
640
|
+
useState,
|
|
641
|
+
useEffect,
|
|
642
|
+
useContext,
|
|
643
|
+
useReducer,
|
|
644
|
+
useCallback,
|
|
645
|
+
useMemo,
|
|
646
|
+
useRef,
|
|
647
|
+
useImperativeHandle,
|
|
648
|
+
useLayoutEffect,
|
|
649
|
+
useDebugValue,
|
|
650
|
+
useDeferredValue,
|
|
651
|
+
useTransition,
|
|
652
|
+
useId,
|
|
653
|
+
useSyncExternalStore,
|
|
654
|
+
useInsertionEffect,
|
|
655
|
+
createContext,
|
|
656
|
+
forwardRef,
|
|
657
|
+
lazy,
|
|
658
|
+
memo,
|
|
659
|
+
startTransition,
|
|
660
|
+
createElement,
|
|
661
|
+
cloneElement,
|
|
662
|
+
isValidElement,
|
|
663
|
+
Children,
|
|
664
|
+
Fragment,
|
|
665
|
+
Profiler,
|
|
666
|
+
StrictMode,
|
|
667
|
+
Suspense,
|
|
668
|
+
Component,
|
|
669
|
+
PureComponent,
|
|
670
|
+
useActionState,
|
|
671
|
+
use,
|
|
672
|
+
} = React;
|
|
673
|
+
`.trim(),
|
|
674
|
+
loader: "js"
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
if (args.path === "react-dom-external") {
|
|
678
|
+
return {
|
|
679
|
+
contents: `
|
|
680
|
+
if (!globalThis.__ONEX_REACT_DOM__) {
|
|
681
|
+
throw new Error('[Theme Bundle] ReactDOM not initialized. Ensure globalThis.__ONEX_REACT_DOM__ is set before loading theme.');
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const ReactDOM = globalThis.__ONEX_REACT_DOM__;
|
|
685
|
+
export default ReactDOM;
|
|
686
|
+
|
|
687
|
+
export const {
|
|
688
|
+
createRoot,
|
|
689
|
+
hydrateRoot,
|
|
690
|
+
flushSync,
|
|
691
|
+
createPortal,
|
|
692
|
+
findDOMNode,
|
|
693
|
+
render,
|
|
694
|
+
hydrate,
|
|
695
|
+
unmountComponentAtNode,
|
|
696
|
+
} = ReactDOM;
|
|
697
|
+
`.trim(),
|
|
698
|
+
loader: "js"
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
if (args.path === "react-jsx-runtime-external") {
|
|
702
|
+
return {
|
|
703
|
+
contents: `
|
|
704
|
+
if (!globalThis.__ONEX_JSX_RUNTIME__) {
|
|
705
|
+
throw new Error('[Theme Bundle] React JSX runtime not initialized. Ensure globalThis.__ONEX_JSX_RUNTIME__ is set before loading theme.');
|
|
706
|
+
}
|
|
707
|
+
const _jsxRuntime = globalThis.__ONEX_JSX_RUNTIME__;
|
|
708
|
+
export const jsx = _jsxRuntime.jsx;
|
|
709
|
+
export const jsxs = _jsxRuntime.jsxs;
|
|
710
|
+
export const Fragment = _jsxRuntime.Fragment;
|
|
711
|
+
`.trim(),
|
|
712
|
+
loader: "js"
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
};
|
|
70
719
|
}
|
|
71
|
-
};
|
|
72
|
-
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
// src/commands/init.ts
|
|
723
|
+
init_logger();
|
|
73
724
|
|
|
74
725
|
// src/utils/validators.ts
|
|
75
726
|
function validateName(name) {
|
|
@@ -89,8 +740,8 @@ function validateThemeName(name) {
|
|
|
89
740
|
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
90
741
|
}
|
|
91
742
|
function pathExists(filePath) {
|
|
92
|
-
const
|
|
93
|
-
return
|
|
743
|
+
const fs11 = __require("fs-extra");
|
|
744
|
+
return fs11.existsSync(filePath);
|
|
94
745
|
}
|
|
95
746
|
function validateCategory(category) {
|
|
96
747
|
const validCategories = [
|
|
@@ -123,6 +774,9 @@ function getValidCategories() {
|
|
|
123
774
|
"contact"
|
|
124
775
|
];
|
|
125
776
|
}
|
|
777
|
+
|
|
778
|
+
// src/utils/file-helpers.ts
|
|
779
|
+
init_logger();
|
|
126
780
|
async function renderTemplate(templatePath, data) {
|
|
127
781
|
const template = await fs.readFile(templatePath, "utf-8");
|
|
128
782
|
return ejs.render(template, data);
|
|
@@ -208,8 +862,10 @@ function getProjectRoot() {
|
|
|
208
862
|
}
|
|
209
863
|
function getThemesDir() {
|
|
210
864
|
const root = getProjectRoot();
|
|
211
|
-
if (fs.existsSync(path.join(root, "themes")))
|
|
212
|
-
|
|
865
|
+
if (fs.existsSync(path.join(root, "themes")))
|
|
866
|
+
return path.join(root, "themes");
|
|
867
|
+
if (fs.existsSync(path.join(root, "src/themes")))
|
|
868
|
+
return path.join(root, "src/themes");
|
|
213
869
|
return path.dirname(root);
|
|
214
870
|
}
|
|
215
871
|
function getFeaturesDir() {
|
|
@@ -679,6 +1335,9 @@ export const homePageConfig: PageConfig = {
|
|
|
679
1335
|
};
|
|
680
1336
|
`;
|
|
681
1337
|
}
|
|
1338
|
+
|
|
1339
|
+
// src/commands/create-section.ts
|
|
1340
|
+
init_logger();
|
|
682
1341
|
async function createSectionCommand(name, options) {
|
|
683
1342
|
logger.header("Create New Section");
|
|
684
1343
|
ensureOneXProject();
|
|
@@ -918,6 +1577,9 @@ export { ${data.sectionName}Schema } from "./${data.sectionName}.schema";
|
|
|
918
1577
|
${hasTemplate ? `export { ${data.sectionNamePascal}Default } from "./${data.sectionName}-default";` : ""}
|
|
919
1578
|
`;
|
|
920
1579
|
}
|
|
1580
|
+
|
|
1581
|
+
// src/commands/create-block.ts
|
|
1582
|
+
init_logger();
|
|
921
1583
|
async function createBlockCommand(name, options) {
|
|
922
1584
|
logger.header("Create New Block");
|
|
923
1585
|
ensureOneXProject();
|
|
@@ -1142,6 +1804,9 @@ export { ${data.blockName}Definition } from "./${data.blockName}.schema";
|
|
|
1142
1804
|
export { ${data.blockNamePascal} } from "./${data.blockName}";
|
|
1143
1805
|
`;
|
|
1144
1806
|
}
|
|
1807
|
+
|
|
1808
|
+
// src/commands/create-component.ts
|
|
1809
|
+
init_logger();
|
|
1145
1810
|
async function createComponentCommand(name, options) {
|
|
1146
1811
|
logger.header("Create New Component");
|
|
1147
1812
|
ensureOneXProject();
|
|
@@ -1346,6 +2011,9 @@ export { ${data.componentName}Definition } from "./${data.componentName}.schema"
|
|
|
1346
2011
|
export { ${data.componentNamePascal} } from "./${data.componentName}";
|
|
1347
2012
|
`;
|
|
1348
2013
|
}
|
|
2014
|
+
|
|
2015
|
+
// src/commands/list.ts
|
|
2016
|
+
init_logger();
|
|
1349
2017
|
async function listCommand(options) {
|
|
1350
2018
|
logger.header("OneX Project Inventory");
|
|
1351
2019
|
ensureOneXProject();
|
|
@@ -1477,7 +2145,11 @@ async function listThemesInfo() {
|
|
|
1477
2145
|
}
|
|
1478
2146
|
logger.newLine();
|
|
1479
2147
|
}
|
|
2148
|
+
|
|
2149
|
+
// src/commands/build.ts
|
|
2150
|
+
init_logger();
|
|
1480
2151
|
async function buildCommand(options) {
|
|
2152
|
+
var _a;
|
|
1481
2153
|
logger.header("Build Theme");
|
|
1482
2154
|
let themePath;
|
|
1483
2155
|
let themeName;
|
|
@@ -1498,7 +2170,11 @@ async function buildCommand(options) {
|
|
|
1498
2170
|
process.exit(1);
|
|
1499
2171
|
}
|
|
1500
2172
|
} else {
|
|
1501
|
-
const isThemeDir = [
|
|
2173
|
+
const isThemeDir = [
|
|
2174
|
+
"theme.config.ts",
|
|
2175
|
+
"bundle-entry.ts",
|
|
2176
|
+
"manifest.ts"
|
|
2177
|
+
].some((f) => fs.existsSync(path.join(process.cwd(), f)));
|
|
1502
2178
|
if (isThemeDir) {
|
|
1503
2179
|
themePath = process.cwd();
|
|
1504
2180
|
themeName = path.basename(themePath);
|
|
@@ -1542,11 +2218,20 @@ async function buildCommand(options) {
|
|
|
1542
2218
|
process.exit(1);
|
|
1543
2219
|
}
|
|
1544
2220
|
logger.stopSpinner(true, "Lint passed");
|
|
1545
|
-
const
|
|
2221
|
+
const pkgJson = fs.readJsonSync(packageJsonPath);
|
|
2222
|
+
const buildScript = ((_a = pkgJson.scripts) == null ? void 0 : _a.build) || "";
|
|
2223
|
+
const isRecursive = buildScript.includes("onex build") || buildScript.includes("onex-cli build");
|
|
1546
2224
|
logger.startSpinner(
|
|
1547
2225
|
options.watch ? "Building (watch mode)..." : "Building..."
|
|
1548
2226
|
);
|
|
1549
|
-
|
|
2227
|
+
let buildSuccess;
|
|
2228
|
+
if (isRecursive) {
|
|
2229
|
+
const { compileStandaloneTheme: compileStandaloneTheme2 } = await Promise.resolve().then(() => (init_compile_theme(), compile_theme_exports));
|
|
2230
|
+
buildSuccess = await compileStandaloneTheme2(themePath, themeName);
|
|
2231
|
+
} else {
|
|
2232
|
+
const buildArgs = options.watch ? ["build", "--watch"] : ["build"];
|
|
2233
|
+
buildSuccess = await runCommand("pnpm", buildArgs, themePath);
|
|
2234
|
+
}
|
|
1550
2235
|
if (!buildSuccess && !options.watch) {
|
|
1551
2236
|
logger.stopSpinner(false, "Build failed");
|
|
1552
2237
|
process.exit(1);
|
|
@@ -1587,6 +2272,9 @@ function runCommand(command, args, cwd) {
|
|
|
1587
2272
|
});
|
|
1588
2273
|
});
|
|
1589
2274
|
}
|
|
2275
|
+
|
|
2276
|
+
// src/commands/upload.ts
|
|
2277
|
+
init_logger();
|
|
1590
2278
|
function getS3Client() {
|
|
1591
2279
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
1592
2280
|
if (adapterMode === "vps") {
|
|
@@ -1626,21 +2314,12 @@ function getBucketName(env) {
|
|
|
1626
2314
|
return environment === "production" ? "onex-themes-prod" : "onex-themes-staging";
|
|
1627
2315
|
}
|
|
1628
2316
|
async function findCompiledThemeDir(themeId, version) {
|
|
1629
|
-
const searchPaths = [
|
|
1630
|
-
path.resolve(process.cwd(), "dist"),
|
|
1631
|
-
path.resolve(
|
|
1632
|
-
process.cwd(),
|
|
1633
|
-
`../../apps/api-server/compiled-themes/${themeId}@${version}`
|
|
1634
|
-
),
|
|
1635
|
-
path.resolve(
|
|
1636
|
-
process.cwd(),
|
|
1637
|
-
`../api-server/compiled-themes/${themeId}@${version}`
|
|
1638
|
-
)
|
|
1639
|
-
];
|
|
2317
|
+
const searchPaths = [path.resolve(process.cwd(), "dist")];
|
|
1640
2318
|
for (const dir of searchPaths) {
|
|
1641
2319
|
if (await fs.pathExists(dir)) {
|
|
1642
|
-
const
|
|
1643
|
-
|
|
2320
|
+
const hasManifest = await fs.pathExists(path.join(dir, "manifest.json"));
|
|
2321
|
+
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"));
|
|
2322
|
+
if (hasManifest || hasThemeEntry) {
|
|
1644
2323
|
return dir;
|
|
1645
2324
|
}
|
|
1646
2325
|
}
|
|
@@ -1743,13 +2422,8 @@ async function uploadCommand(options) {
|
|
|
1743
2422
|
`Compiled theme not found for ${themeId}@${version}. Run 'onex build' first.`
|
|
1744
2423
|
)
|
|
1745
2424
|
);
|
|
1746
|
-
logger.info(
|
|
1747
|
-
|
|
1748
|
-
`Expected locations:
|
|
1749
|
-
- ./dist/
|
|
1750
|
-
- ../../apps/api-server/compiled-themes/${themeId}@${version}/`
|
|
1751
|
-
)
|
|
1752
|
-
);
|
|
2425
|
+
logger.info(chalk4.gray(`Expected location:
|
|
2426
|
+
- ./dist/`));
|
|
1753
2427
|
process.exit(1);
|
|
1754
2428
|
}
|
|
1755
2429
|
spinner.succeed(`Found compiled theme at: ${compiledDir}`);
|
|
@@ -1856,9 +2530,7 @@ async function uploadCommand(options) {
|
|
|
1856
2530
|
);
|
|
1857
2531
|
console.log(chalk4.cyan(" Bucket: ") + chalk4.white(bucket));
|
|
1858
2532
|
console.log(
|
|
1859
|
-
chalk4.cyan(" Files: ") + chalk4.white(
|
|
1860
|
-
`bundle.zip${sourceUploaded ? " + source.zip" : ""}`
|
|
1861
|
-
)
|
|
2533
|
+
chalk4.cyan(" Files: ") + chalk4.white(`bundle.zip${sourceUploaded ? " + source.zip" : ""}`)
|
|
1862
2534
|
);
|
|
1863
2535
|
console.log(
|
|
1864
2536
|
chalk4.cyan(" Path: ") + chalk4.gray(`s3://${bucket}/themes/${themeId}/${version}/`)
|
|
@@ -1870,6 +2542,9 @@ async function uploadCommand(options) {
|
|
|
1870
2542
|
process.exit(1);
|
|
1871
2543
|
}
|
|
1872
2544
|
}
|
|
2545
|
+
|
|
2546
|
+
// src/commands/download.ts
|
|
2547
|
+
init_logger();
|
|
1873
2548
|
function getS3Client2() {
|
|
1874
2549
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
1875
2550
|
if (adapterMode === "vps") {
|
|
@@ -2017,11 +2692,7 @@ function showDownloadFailureHelp(themeId, bucket) {
|
|
|
2017
2692
|
);
|
|
2018
2693
|
console.log();
|
|
2019
2694
|
console.log(chalk4.white("4. Verify theme exists in S3:"));
|
|
2020
|
-
console.log(
|
|
2021
|
-
chalk4.gray(
|
|
2022
|
-
` aws s3 ls s3://${bucket}/themes/${themeId}/`
|
|
2023
|
-
)
|
|
2024
|
-
);
|
|
2695
|
+
console.log(chalk4.gray(` aws s3 ls s3://${bucket}/themes/${themeId}/`));
|
|
2025
2696
|
console.log();
|
|
2026
2697
|
}
|
|
2027
2698
|
async function downloadCommand(options) {
|
|
@@ -2097,6 +2768,9 @@ async function downloadCommand(options) {
|
|
|
2097
2768
|
process.exit(1);
|
|
2098
2769
|
}
|
|
2099
2770
|
}
|
|
2771
|
+
|
|
2772
|
+
// src/commands/clone.ts
|
|
2773
|
+
init_logger();
|
|
2100
2774
|
function getS3Client3() {
|
|
2101
2775
|
const adapterMode = (process.env.ADAPTER_MODE || "aws").trim().toLowerCase();
|
|
2102
2776
|
if (adapterMode === "vps") {
|
|
@@ -2200,17 +2874,100 @@ function runInstall(cwd) {
|
|
|
2200
2874
|
proc.on("error", () => resolve(false));
|
|
2201
2875
|
});
|
|
2202
2876
|
}
|
|
2877
|
+
async function promptThemeName(originalName) {
|
|
2878
|
+
const { default: inquirer5 } = await import('inquirer');
|
|
2879
|
+
const { themeName } = await inquirer5.prompt([
|
|
2880
|
+
{
|
|
2881
|
+
type: "input",
|
|
2882
|
+
name: "themeName",
|
|
2883
|
+
message: "New theme name (kebab-case):",
|
|
2884
|
+
default: `my-${originalName}`,
|
|
2885
|
+
validate: (input) => {
|
|
2886
|
+
if (!/^[a-z][a-z0-9-]*$/.test(input)) {
|
|
2887
|
+
return "Theme name must be kebab-case (lowercase letters, numbers, hyphens)";
|
|
2888
|
+
}
|
|
2889
|
+
if (input === originalName) {
|
|
2890
|
+
return `Name must differ from the original theme "${originalName}"`;
|
|
2891
|
+
}
|
|
2892
|
+
return true;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
]);
|
|
2896
|
+
return themeName;
|
|
2897
|
+
}
|
|
2898
|
+
async function renameTheme(themeDir, oldName, newName) {
|
|
2899
|
+
const oldPrefix = `${oldName}-`;
|
|
2900
|
+
const newPrefix = `${newName}-`;
|
|
2901
|
+
const newDisplayName = newName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2902
|
+
const pkgPath = path.join(themeDir, "package.json");
|
|
2903
|
+
if (await fs.pathExists(pkgPath)) {
|
|
2904
|
+
const pkg = await fs.readJson(pkgPath);
|
|
2905
|
+
pkg.name = `@onex-themes/${newName}`;
|
|
2906
|
+
if (pkg.description) {
|
|
2907
|
+
pkg.description = pkg.description.replace(
|
|
2908
|
+
new RegExp(oldName, "gi"),
|
|
2909
|
+
newDisplayName
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
pkg.version = "1.0.0";
|
|
2913
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
2914
|
+
}
|
|
2915
|
+
const configPath = path.join(themeDir, "theme.config.ts");
|
|
2916
|
+
if (await fs.pathExists(configPath)) {
|
|
2917
|
+
let content = await fs.readFile(configPath, "utf-8");
|
|
2918
|
+
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
2919
|
+
content = content.replace(
|
|
2920
|
+
/name:\s*"[^"]*Theme"/,
|
|
2921
|
+
`name: "${newDisplayName} Theme"`
|
|
2922
|
+
);
|
|
2923
|
+
await fs.writeFile(configPath, content);
|
|
2924
|
+
}
|
|
2925
|
+
const layoutPath = path.join(themeDir, "theme.layout.ts");
|
|
2926
|
+
if (await fs.pathExists(layoutPath)) {
|
|
2927
|
+
let content = await fs.readFile(layoutPath, "utf-8");
|
|
2928
|
+
content = content.replace(/id:\s*"[^"]*"/, `id: "${newName}"`);
|
|
2929
|
+
content = content.replace(
|
|
2930
|
+
/name:\s*"[^"]*Theme"/,
|
|
2931
|
+
`name: "${newDisplayName} Theme"`
|
|
2932
|
+
);
|
|
2933
|
+
await fs.writeFile(layoutPath, content);
|
|
2934
|
+
}
|
|
2935
|
+
const oldDisplayName = oldName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
2936
|
+
const tsFiles = await glob("**/*.ts", { cwd: themeDir, nodir: true });
|
|
2937
|
+
for (const file of tsFiles) {
|
|
2938
|
+
const filePath = path.join(themeDir, file);
|
|
2939
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
2940
|
+
const original = content;
|
|
2941
|
+
content = content.replace(
|
|
2942
|
+
new RegExp(`"${oldPrefix}`, "g"),
|
|
2943
|
+
`"${newPrefix}`
|
|
2944
|
+
);
|
|
2945
|
+
content = content.replace(
|
|
2946
|
+
new RegExp(`themeId:\\s*"${oldName}"`, "g"),
|
|
2947
|
+
`themeId: "${newName}"`
|
|
2948
|
+
);
|
|
2949
|
+
content = content.replace(
|
|
2950
|
+
new RegExp(`${oldDisplayName} Theme`, "g"),
|
|
2951
|
+
`${newDisplayName} Theme`
|
|
2952
|
+
);
|
|
2953
|
+
if (content !== original) {
|
|
2954
|
+
await fs.writeFile(filePath, content);
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2203
2958
|
async function cloneCommand(themeName, options) {
|
|
2204
2959
|
logger.header("Clone Theme Source");
|
|
2960
|
+
let newName = options.name;
|
|
2961
|
+
if (!newName) {
|
|
2962
|
+
newName = await promptThemeName(themeName);
|
|
2963
|
+
}
|
|
2205
2964
|
const spinner = ora("Initializing clone...").start();
|
|
2206
2965
|
try {
|
|
2207
2966
|
const bucket = options.bucket || getBucketName3(options.environment);
|
|
2208
|
-
const outputDir = options.output || path.resolve(process.cwd(),
|
|
2967
|
+
const outputDir = options.output || path.resolve(process.cwd(), newName);
|
|
2209
2968
|
const s3Client = getS3Client3();
|
|
2210
2969
|
if (await fs.pathExists(outputDir)) {
|
|
2211
|
-
spinner.fail(
|
|
2212
|
-
chalk4.red(`Directory already exists: ${outputDir}`)
|
|
2213
|
-
);
|
|
2970
|
+
spinner.fail(chalk4.red(`Directory already exists: ${outputDir}`));
|
|
2214
2971
|
logger.info(
|
|
2215
2972
|
chalk4.gray(
|
|
2216
2973
|
"Use -o to specify a different output directory, or remove the existing directory."
|
|
@@ -2224,9 +2981,7 @@ async function cloneCommand(themeName, options) {
|
|
|
2224
2981
|
version = await resolveLatestVersion2(s3Client, bucket, themeName);
|
|
2225
2982
|
spinner.succeed(`Resolved latest version: ${chalk4.cyan(version)}`);
|
|
2226
2983
|
}
|
|
2227
|
-
spinner.start(
|
|
2228
|
-
`Downloading source.zip for ${themeName}@${version}...`
|
|
2229
|
-
);
|
|
2984
|
+
spinner.start(`Downloading source.zip for ${themeName}@${version}...`);
|
|
2230
2985
|
const s3Key = `themes/${themeName}/${version}/source.zip`;
|
|
2231
2986
|
let zipBuffer;
|
|
2232
2987
|
try {
|
|
@@ -2244,9 +2999,7 @@ async function cloneCommand(themeName, options) {
|
|
|
2244
2999
|
chalk4.yellow("The theme source may not have been uploaded yet.")
|
|
2245
3000
|
);
|
|
2246
3001
|
console.log(
|
|
2247
|
-
chalk4.gray(
|
|
2248
|
-
`Upload source with: onex upload --theme ${themeName}`
|
|
2249
|
-
)
|
|
3002
|
+
chalk4.gray(`Upload source with: onex upload --theme ${themeName}`)
|
|
2250
3003
|
);
|
|
2251
3004
|
console.log();
|
|
2252
3005
|
process.exit(1);
|
|
@@ -2259,6 +3012,13 @@ async function cloneCommand(themeName, options) {
|
|
|
2259
3012
|
zip.extractAllTo(outputDir, true);
|
|
2260
3013
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
2261
3014
|
spinner.succeed(`Extracted ${entries.length} files`);
|
|
3015
|
+
spinner.start(
|
|
3016
|
+
`Renaming theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}...`
|
|
3017
|
+
);
|
|
3018
|
+
await renameTheme(outputDir, themeName, newName);
|
|
3019
|
+
spinner.succeed(
|
|
3020
|
+
`Renamed theme: ${chalk4.gray(themeName)} \u2192 ${chalk4.cyan(newName)}`
|
|
3021
|
+
);
|
|
2262
3022
|
if (options.install !== false) {
|
|
2263
3023
|
const hasPkgJson = await fs.pathExists(
|
|
2264
3024
|
path.join(outputDir, "package.json")
|
|
@@ -2281,15 +3041,14 @@ async function cloneCommand(themeName, options) {
|
|
|
2281
3041
|
logger.success(chalk4.green.bold("Theme cloned successfully!"));
|
|
2282
3042
|
console.log();
|
|
2283
3043
|
console.log(
|
|
2284
|
-
chalk4.cyan("
|
|
3044
|
+
chalk4.cyan(" Source: ") + chalk4.gray(`${themeName}@${version}`)
|
|
2285
3045
|
);
|
|
3046
|
+
console.log(chalk4.cyan(" Theme: ") + chalk4.white(newName));
|
|
2286
3047
|
console.log(chalk4.cyan(" Location: ") + chalk4.white(outputDir));
|
|
2287
3048
|
console.log(chalk4.cyan(" Files: ") + chalk4.white(entries.length));
|
|
2288
3049
|
console.log();
|
|
2289
3050
|
console.log(chalk4.cyan("Next steps:"));
|
|
2290
|
-
console.log(
|
|
2291
|
-
chalk4.gray(` cd ${path.relative(process.cwd(), outputDir)}`)
|
|
2292
|
-
);
|
|
3051
|
+
console.log(chalk4.gray(` cd ${path.relative(process.cwd(), outputDir)}`));
|
|
2293
3052
|
if (options.install === false) {
|
|
2294
3053
|
console.log(chalk4.gray(" pnpm install"));
|
|
2295
3054
|
}
|
|
@@ -2302,6 +3061,9 @@ async function cloneCommand(themeName, options) {
|
|
|
2302
3061
|
}
|
|
2303
3062
|
}
|
|
2304
3063
|
|
|
3064
|
+
// src/index.ts
|
|
3065
|
+
init_logger();
|
|
3066
|
+
|
|
2305
3067
|
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 };
|
|
2306
3068
|
//# sourceMappingURL=index.mjs.map
|
|
2307
3069
|
//# sourceMappingURL=index.mjs.map
|