@onexapis/cli 1.1.10 → 1.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +282 -17
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +282 -17
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +282 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +282 -17
- package/dist/index.mjs.map +1 -1
- package/dist/preview/preview-app.tsx +42 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -110,8 +110,37 @@ async function resolveNodeModulesFile(startDir, relativePath) {
|
|
|
110
110
|
}
|
|
111
111
|
return null;
|
|
112
112
|
}
|
|
113
|
+
async function scanImportsFromPackage(sourceDir, packageName) {
|
|
114
|
+
const result = {};
|
|
115
|
+
const escapedPkg = packageName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
116
|
+
const importRegex = new RegExp(
|
|
117
|
+
`(?:import|export)\\s+(?:type\\s+)?\\{([^}]+)\\}\\s+from\\s+["']${escapedPkg}(/[\\w./-]+)?["']`,
|
|
118
|
+
"g"
|
|
119
|
+
);
|
|
120
|
+
const sourceFiles = await glob("**/*.{ts,tsx}", {
|
|
121
|
+
cwd: sourceDir,
|
|
122
|
+
ignore: ["node_modules/**", "dist/**"]
|
|
123
|
+
});
|
|
124
|
+
for (const file of sourceFiles) {
|
|
125
|
+
try {
|
|
126
|
+
const content = await fs6.readFile(path7.join(sourceDir, file), "utf-8");
|
|
127
|
+
for (const match of content.matchAll(importRegex)) {
|
|
128
|
+
const subpath = match[2] ? match[2].slice(1) : "";
|
|
129
|
+
if (!result[subpath]) result[subpath] = /* @__PURE__ */ new Set();
|
|
130
|
+
for (const name of match[1].split(",")) {
|
|
131
|
+
let original = name.trim().split(/\s+as\s+/)[0].trim();
|
|
132
|
+
if (original.startsWith("type ")) continue;
|
|
133
|
+
if (original) result[subpath].add(original);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
113
141
|
function createCoreGlobalPlugin(themePath) {
|
|
114
142
|
const exportsBySubpath = {};
|
|
143
|
+
let scanPromise = null;
|
|
115
144
|
return {
|
|
116
145
|
name: "core-global",
|
|
117
146
|
setup(build2) {
|
|
@@ -120,6 +149,16 @@ function createCoreGlobalPlugin(themePath) {
|
|
|
120
149
|
namespace: "core-global"
|
|
121
150
|
}));
|
|
122
151
|
build2.onLoad({ filter: /.*/, namespace: "core-global" }, async (args) => {
|
|
152
|
+
if (!scanPromise) {
|
|
153
|
+
scanPromise = scanImportsFromPackage(themePath, "@onexapis/core").then((scanned) => {
|
|
154
|
+
for (const [subpath2, names] of Object.entries(scanned)) {
|
|
155
|
+
const cacheKey2 = subpath2 || "__root__";
|
|
156
|
+
exportsBySubpath[cacheKey2] = [...names];
|
|
157
|
+
}
|
|
158
|
+
}).catch(() => {
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
await scanPromise;
|
|
123
162
|
const match = args.path.match(/^@onexapis\/core(\/(.+))?$/);
|
|
124
163
|
const subpath = match?.[2] || "";
|
|
125
164
|
const moduleAccess = subpath ? `['${subpath}']` : "";
|
|
@@ -183,6 +222,160 @@ ${namedExportLines}
|
|
|
183
222
|
}
|
|
184
223
|
};
|
|
185
224
|
}
|
|
225
|
+
function createThemeDepsStubPlugin(themePath) {
|
|
226
|
+
return {
|
|
227
|
+
name: "theme-deps-stub",
|
|
228
|
+
setup(build2) {
|
|
229
|
+
const tryResolveOrStub = (filter, namespace) => {
|
|
230
|
+
build2.onResolve({ filter }, async (args) => {
|
|
231
|
+
if (args.pluginData?.skipStub) return void 0;
|
|
232
|
+
try {
|
|
233
|
+
const result = await build2.resolve(args.path, {
|
|
234
|
+
kind: args.kind,
|
|
235
|
+
resolveDir: args.resolveDir || themePath,
|
|
236
|
+
importer: args.importer,
|
|
237
|
+
namespace: "file",
|
|
238
|
+
pluginData: { skipStub: true }
|
|
239
|
+
});
|
|
240
|
+
if (!result.errors.length) return result;
|
|
241
|
+
} catch {
|
|
242
|
+
}
|
|
243
|
+
return { path: args.path, namespace };
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
tryResolveOrStub(/^next\//, "next-stub");
|
|
247
|
+
build2.onLoad({ filter: /.*/, namespace: "next-stub" }, (args) => {
|
|
248
|
+
const stubs = {
|
|
249
|
+
"next/image": `
|
|
250
|
+
import React from 'react';
|
|
251
|
+
const Image = (props) => {
|
|
252
|
+
const { src, alt, width, height, fill, priority, ...rest } = props;
|
|
253
|
+
const imgSrc = typeof src === 'object' ? src.src : src;
|
|
254
|
+
return React.createElement('img', { src: imgSrc, alt, width: fill ? undefined : width, height: fill ? undefined : height, loading: priority ? 'eager' : 'lazy', ...rest });
|
|
255
|
+
};
|
|
256
|
+
export default Image;
|
|
257
|
+
`,
|
|
258
|
+
"next/link": `
|
|
259
|
+
import React from 'react';
|
|
260
|
+
const Link = ({ href, children, ...rest }) => React.createElement('a', { href, ...rest }, children);
|
|
261
|
+
export default Link;
|
|
262
|
+
`,
|
|
263
|
+
"next/navigation": `
|
|
264
|
+
export function useRouter() { return { push(u){window.location.href=u}, replace(u){window.location.href=u}, back(){window.history.back()}, forward(){window.history.forward()}, refresh(){window.location.reload()}, prefetch(){} }; }
|
|
265
|
+
export function usePathname() { return window.location.pathname; }
|
|
266
|
+
export function useSearchParams() { return new URLSearchParams(window.location.search); }
|
|
267
|
+
export function useParams() { return {}; }
|
|
268
|
+
export function redirect(url) { window.location.href = url; }
|
|
269
|
+
export function notFound() { throw new Error('Not Found'); }
|
|
270
|
+
`,
|
|
271
|
+
"next/headers": `
|
|
272
|
+
export function cookies() { return { get(){}, getAll(){ return []; }, set(){}, delete(){}, has(){ return false; } }; }
|
|
273
|
+
export function headers() { return new Headers(); }
|
|
274
|
+
`
|
|
275
|
+
};
|
|
276
|
+
return {
|
|
277
|
+
contents: stubs[args.path] || "export default {};",
|
|
278
|
+
loader: "jsx",
|
|
279
|
+
resolveDir: themePath
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
const lucideImports = /* @__PURE__ */ new Set();
|
|
283
|
+
let lucideThemeScanned = false;
|
|
284
|
+
tryResolveOrStub(/^lucide-react/, "lucide-stub");
|
|
285
|
+
build2.onLoad({ filter: /.*/, namespace: "lucide-stub" }, async () => {
|
|
286
|
+
if (!lucideThemeScanned) {
|
|
287
|
+
lucideThemeScanned = true;
|
|
288
|
+
try {
|
|
289
|
+
const scanned = await scanImportsFromPackage(themePath, "lucide-react");
|
|
290
|
+
for (const names of Object.values(scanned)) {
|
|
291
|
+
for (const name of names) lucideImports.add(name);
|
|
292
|
+
}
|
|
293
|
+
} catch {
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const iconNames = [...lucideImports];
|
|
297
|
+
const exports$1 = iconNames.map((n) => `icon as ${n}`).join(", ");
|
|
298
|
+
return {
|
|
299
|
+
contents: `
|
|
300
|
+
const icon = (props) => null;
|
|
301
|
+
export { ${exports$1} };
|
|
302
|
+
export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true : icon });
|
|
303
|
+
`.trim(),
|
|
304
|
+
loader: "jsx"
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
tryResolveOrStub(/^framer-motion/, "motion-stub");
|
|
308
|
+
build2.onLoad({ filter: /.*/, namespace: "motion-stub" }, () => ({
|
|
309
|
+
contents: `
|
|
310
|
+
import React from 'react';
|
|
311
|
+
const handler = { get: (_, name) => {
|
|
312
|
+
if (name === '__esModule') return true;
|
|
313
|
+
return React.forwardRef((props, ref) => React.createElement(name, { ...props, ref }));
|
|
314
|
+
}};
|
|
315
|
+
export const motion = new Proxy({}, handler);
|
|
316
|
+
export const AnimatePresence = ({ children }) => children || null;
|
|
317
|
+
export function useInView() { return true; }
|
|
318
|
+
export default { motion, AnimatePresence, useInView };
|
|
319
|
+
`.trim(),
|
|
320
|
+
loader: "jsx",
|
|
321
|
+
resolveDir: themePath
|
|
322
|
+
}));
|
|
323
|
+
tryResolveOrStub(/^sonner$/, "sonner-stub");
|
|
324
|
+
build2.onLoad({ filter: /.*/, namespace: "sonner-stub" }, () => ({
|
|
325
|
+
contents: `
|
|
326
|
+
export const toast = new Proxy(() => {}, { get: () => () => {} });
|
|
327
|
+
export const Toaster = () => null;
|
|
328
|
+
export default { toast, Toaster };
|
|
329
|
+
`.trim(),
|
|
330
|
+
loader: "jsx"
|
|
331
|
+
}));
|
|
332
|
+
tryResolveOrStub(/^react-hook-form$/, "rhf-stub");
|
|
333
|
+
build2.onLoad({ filter: /.*/, namespace: "rhf-stub" }, () => ({
|
|
334
|
+
contents: `
|
|
335
|
+
export function useForm() {
|
|
336
|
+
return {
|
|
337
|
+
register: () => ({}),
|
|
338
|
+
handleSubmit: (fn) => (e) => { e?.preventDefault?.(); fn({}); },
|
|
339
|
+
formState: { errors: {}, isSubmitting: false, isValid: true },
|
|
340
|
+
watch: () => undefined,
|
|
341
|
+
setValue: () => {},
|
|
342
|
+
reset: () => {},
|
|
343
|
+
control: {},
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
export function useController() { return { field: {}, fieldState: {} }; }
|
|
347
|
+
export function useFormContext() { return useForm(); }
|
|
348
|
+
`.trim(),
|
|
349
|
+
loader: "js"
|
|
350
|
+
}));
|
|
351
|
+
tryResolveOrStub(/^@hookform\/resolvers/, "hookform-resolvers-stub");
|
|
352
|
+
build2.onLoad({ filter: /.*/, namespace: "hookform-resolvers-stub" }, () => ({
|
|
353
|
+
contents: `export function zodResolver() { return () => ({ values: {}, errors: {} }); }`,
|
|
354
|
+
loader: "js"
|
|
355
|
+
}));
|
|
356
|
+
tryResolveOrStub(/^next-intl$/, "next-intl-stub");
|
|
357
|
+
build2.onLoad({ filter: /.*/, namespace: "next-intl-stub" }, () => ({
|
|
358
|
+
contents: `
|
|
359
|
+
export function useTranslations(ns) {
|
|
360
|
+
return (key) => ns ? ns + '.' + key : key;
|
|
361
|
+
}
|
|
362
|
+
export function useLocale() { return 'en'; }
|
|
363
|
+
export function useMessages() { return {}; }
|
|
364
|
+
`.trim(),
|
|
365
|
+
loader: "js"
|
|
366
|
+
}));
|
|
367
|
+
tryResolveOrStub(/^zod$/, "zod-stub");
|
|
368
|
+
build2.onLoad({ filter: /.*/, namespace: "zod-stub" }, () => ({
|
|
369
|
+
contents: `
|
|
370
|
+
const schema = () => ({ parse: (v) => v, safeParse: (v) => ({ success: true, data: v }), optional: schema, min: schema, max: schema, email: schema, url: schema, regex: schema, refine: schema, transform: schema });
|
|
371
|
+
export const z = { string: schema, number: schema, boolean: schema, object: (s) => ({ ...schema(), shape: s }), array: schema, enum: schema, union: schema, literal: schema, infer: undefined };
|
|
372
|
+
export default z;
|
|
373
|
+
`.trim(),
|
|
374
|
+
loader: "js"
|
|
375
|
+
}));
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
186
379
|
async function generateThemeData(themePath, outputDir, themeId) {
|
|
187
380
|
const { createJiti } = await import('jiti');
|
|
188
381
|
const jiti = createJiti(import.meta.url);
|
|
@@ -417,7 +610,7 @@ async function compileStandaloneTheme(themePath, themeName) {
|
|
|
417
610
|
banner: {
|
|
418
611
|
js: '"use client";'
|
|
419
612
|
},
|
|
420
|
-
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath)],
|
|
613
|
+
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath), createThemeDepsStubPlugin(themePath)],
|
|
421
614
|
external: [],
|
|
422
615
|
alias: {
|
|
423
616
|
events: "events/",
|
|
@@ -499,7 +692,7 @@ async function compileStandaloneThemeDev(themePath, themeName) {
|
|
|
499
692
|
banner: {
|
|
500
693
|
js: '"use client";'
|
|
501
694
|
},
|
|
502
|
-
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath)],
|
|
695
|
+
plugins: [reactGlobalPlugin, createCoreGlobalPlugin(themePath), createThemeDepsStubPlugin(themePath)],
|
|
503
696
|
external: [],
|
|
504
697
|
alias: {
|
|
505
698
|
events: "events/",
|
|
@@ -610,6 +803,8 @@ ${locations.join("\n")}`
|
|
|
610
803
|
loader: "js"
|
|
611
804
|
};
|
|
612
805
|
});
|
|
806
|
+
const lucideIconNames = /* @__PURE__ */ new Set();
|
|
807
|
+
let lucideScanned = false;
|
|
613
808
|
build2.onResolve({ filter: /^lucide-react/ }, async (args) => {
|
|
614
809
|
if (args.pluginData?.skipStub) return void 0;
|
|
615
810
|
try {
|
|
@@ -625,23 +820,93 @@ ${locations.join("\n")}`
|
|
|
625
820
|
}
|
|
626
821
|
return { path: args.path, namespace: "lucide-stub" };
|
|
627
822
|
});
|
|
628
|
-
build2.onLoad({ filter: /.*/, namespace: "lucide-stub" }, () =>
|
|
629
|
-
|
|
630
|
-
|
|
823
|
+
build2.onLoad({ filter: /.*/, namespace: "lucide-stub" }, async () => {
|
|
824
|
+
if (!lucideScanned) {
|
|
825
|
+
lucideScanned = true;
|
|
826
|
+
const coreSrcCandidates = [
|
|
827
|
+
path7.join(themePath, "node_modules", "@onexapis", "core", "src"),
|
|
828
|
+
path7.join(themePath, "..", "..", "packages", "core", "src"),
|
|
829
|
+
// monorepo sibling
|
|
830
|
+
path7.join(__dirname, "..", "..", "..", "..", "packages", "core", "src")
|
|
831
|
+
// from CLI src
|
|
832
|
+
];
|
|
833
|
+
let coreSourceDir = null;
|
|
834
|
+
for (const candidate of coreSrcCandidates) {
|
|
835
|
+
try {
|
|
836
|
+
await fs6.access(candidate);
|
|
837
|
+
coreSourceDir = candidate;
|
|
838
|
+
break;
|
|
839
|
+
} catch {
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (coreSourceDir) {
|
|
843
|
+
try {
|
|
844
|
+
const scanned = await scanImportsFromPackage(coreSourceDir, "lucide-react");
|
|
845
|
+
for (const names of Object.values(scanned)) {
|
|
846
|
+
for (const name of names) lucideIconNames.add(name);
|
|
847
|
+
}
|
|
848
|
+
} catch {
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
try {
|
|
852
|
+
const scanned = await scanImportsFromPackage(themePath, "lucide-react");
|
|
853
|
+
for (const names of Object.values(scanned)) {
|
|
854
|
+
for (const name of names) lucideIconNames.add(name);
|
|
855
|
+
}
|
|
856
|
+
} catch {
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (lucideIconNames.size === 0) {
|
|
860
|
+
const fallbackIcons = [
|
|
861
|
+
"Check",
|
|
862
|
+
"ChevronDown",
|
|
863
|
+
"XCircle",
|
|
864
|
+
"AlertTriangle",
|
|
865
|
+
"CheckCircle",
|
|
866
|
+
"Info",
|
|
867
|
+
"X",
|
|
868
|
+
"XIcon",
|
|
869
|
+
"CircleIcon",
|
|
870
|
+
"Star",
|
|
871
|
+
"ShoppingCart",
|
|
872
|
+
"ChevronRight",
|
|
873
|
+
"ChevronLeft",
|
|
874
|
+
"ChevronUp",
|
|
875
|
+
"Search",
|
|
876
|
+
"Menu",
|
|
877
|
+
"Heart",
|
|
878
|
+
"User",
|
|
879
|
+
"Trash2",
|
|
880
|
+
"Plus",
|
|
881
|
+
"Minus",
|
|
882
|
+
"Eye",
|
|
883
|
+
"EyeOff",
|
|
884
|
+
"ArrowRight",
|
|
885
|
+
"ArrowLeft",
|
|
886
|
+
"ExternalLink",
|
|
887
|
+
"Mail",
|
|
888
|
+
"Phone",
|
|
889
|
+
"MapPin",
|
|
890
|
+
"Calendar",
|
|
891
|
+
"Clock",
|
|
892
|
+
"Facebook",
|
|
893
|
+
"Twitter",
|
|
894
|
+
"Instagram",
|
|
895
|
+
"Linkedin",
|
|
896
|
+
"Github"
|
|
897
|
+
];
|
|
898
|
+
for (const icon of fallbackIcons) lucideIconNames.add(icon);
|
|
899
|
+
}
|
|
900
|
+
const iconExports = [...lucideIconNames].map((n) => `icon as ${n}`).join(", ");
|
|
901
|
+
return {
|
|
902
|
+
contents: `
|
|
631
903
|
const icon = (props) => null;
|
|
632
|
-
export {
|
|
633
|
-
export { icon as CheckCircle, icon as Info, icon as X, icon as XIcon };
|
|
634
|
-
export { icon as CircleIcon, icon as Star, icon as ShoppingCart };
|
|
635
|
-
export { icon as ChevronRight, icon as ChevronLeft, icon as ChevronUp };
|
|
636
|
-
export { icon as Search, icon as Menu, icon as Heart, icon as User };
|
|
637
|
-
export { icon as Trash2, icon as Plus, icon as Minus, icon as Eye, icon as EyeOff };
|
|
638
|
-
export { icon as ArrowRight, icon as ArrowLeft, icon as ExternalLink, icon as Mail };
|
|
639
|
-
export { icon as Phone, icon as MapPin, icon as Calendar, icon as Clock };
|
|
640
|
-
export { icon as Facebook, icon as Twitter, icon as Instagram, icon as Linkedin, icon as Github };
|
|
904
|
+
export { ${iconExports} };
|
|
641
905
|
export default new Proxy({}, { get: (_, name) => name === '__esModule' ? true : icon });
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
906
|
+
`.trim(),
|
|
907
|
+
loader: "jsx"
|
|
908
|
+
};
|
|
909
|
+
});
|
|
645
910
|
build2.onResolve({ filter: /^framer-motion/ }, async (args) => {
|
|
646
911
|
if (args.pluginData?.skipStub) return void 0;
|
|
647
912
|
try {
|