@lytjs/cli 6.4.0 → 6.5.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/dist/create.cjs +95 -10
- package/dist/create.cjs.map +1 -1
- package/dist/create.mjs +95 -10
- package/dist/create.mjs.map +1 -1
- package/dist/index.cjs +868 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.mjs +849 -20
- package/dist/index.mjs.map +1 -1
- package/dist/lyt.cjs +868 -19
- package/dist/lyt.cjs.map +1 -1
- package/dist/lyt.d.mts +1 -1
- package/dist/lyt.d.ts +1 -1
- package/dist/lyt.mjs +849 -20
- package/dist/lyt.mjs.map +1 -1
- package/lyt-cli.js +3 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
3
4
|
import { join, resolve, dirname } from 'path';
|
|
4
5
|
import { execSync, spawn } from 'child_process';
|
|
5
6
|
|
|
@@ -60,8 +61,8 @@ function writeFile(filePath, content) {
|
|
|
60
61
|
function readFile(filePath) {
|
|
61
62
|
return readFileSync(filePath, "utf-8");
|
|
62
63
|
}
|
|
63
|
-
function exists(
|
|
64
|
-
return existsSync(
|
|
64
|
+
function exists(path2) {
|
|
65
|
+
return existsSync(path2);
|
|
65
66
|
}
|
|
66
67
|
function isEmptyDir(dir) {
|
|
67
68
|
if (!existsSync(dir)) return true;
|
|
@@ -441,12 +442,19 @@ export const useCounterStore = defineStore('counter', () => {
|
|
|
441
442
|
writeFile(join(targetDir, "src", "stores", "counter.ts"), counterStore);
|
|
442
443
|
}
|
|
443
444
|
if (isSsr) {
|
|
444
|
-
const entryServer = `import { createSSRApp } from '@lytjs/core';
|
|
445
|
+
const entryServer = `import { createSSRApp, h } from '@lytjs/core';
|
|
446
|
+
import { renderToString } from '@lytjs/ssr';
|
|
445
447
|
import App from './App.lyt';
|
|
446
448
|
|
|
447
449
|
export async function render(url: string) {
|
|
448
|
-
const app = createSSRApp(
|
|
449
|
-
|
|
450
|
+
const app = createSSRApp({
|
|
451
|
+
render() {
|
|
452
|
+
return h(App);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
const html = await renderToString(app);
|
|
457
|
+
return html;
|
|
450
458
|
}
|
|
451
459
|
`;
|
|
452
460
|
writeFile(join(targetDir, "src/entry-server.ts"), entryServer);
|
|
@@ -460,36 +468,114 @@ app.mount('#app');
|
|
|
460
468
|
const serverTs = `/**
|
|
461
469
|
* LytJS SSR Server
|
|
462
470
|
*
|
|
463
|
-
*
|
|
471
|
+
* Complete SSR server with Vite dev server and production build support.
|
|
472
|
+
* Supports streaming SSR, route prefetching, and static file serving.
|
|
464
473
|
*/
|
|
465
474
|
|
|
466
475
|
import fs from 'fs';
|
|
467
476
|
import path from 'path';
|
|
468
477
|
import { fileURLToPath } from 'url';
|
|
478
|
+
import http from 'http';
|
|
469
479
|
|
|
470
480
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
471
481
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
482
|
+
const DIST_DIR = path.join(__dirname, 'dist');
|
|
483
|
+
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
484
|
+
|
|
485
|
+
interface RenderOptions {
|
|
486
|
+
url: string;
|
|
487
|
+
template: string;
|
|
488
|
+
manifest?: Record<string, string[]>;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
async function renderPage({ url, template, manifest }: RenderOptions): Promise<string> {
|
|
492
|
+
let app: any;
|
|
493
|
+
let vite: any;
|
|
494
|
+
|
|
495
|
+
if (!isProduction) {
|
|
496
|
+
const { createServer: createViteServer } = await import('vite');
|
|
497
|
+
vite = await createViteServer({
|
|
498
|
+
server: { middlewareMode: true },
|
|
499
|
+
appType: 'custom',
|
|
500
|
+
});
|
|
501
|
+
app = (await vite.ssrLoadModule(path.join(__dirname, 'src/entry-server.ts'))).default;
|
|
502
|
+
} else {
|
|
503
|
+
app = (await import(path.join(DIST_DIR, 'server/entry-server.js'))).default;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const html = await app.render(url);
|
|
507
|
+
return template.replace('<!--app-html-->', html);
|
|
508
|
+
}
|
|
472
509
|
|
|
473
510
|
async function createServer() {
|
|
474
|
-
let resolve: any;
|
|
475
511
|
let vite: any;
|
|
476
512
|
|
|
513
|
+
// Load index.html template
|
|
514
|
+
let template: string;
|
|
515
|
+
|
|
477
516
|
if (!isProduction) {
|
|
478
517
|
const { createServer: createViteServer } = await import('vite');
|
|
479
518
|
vite = await createViteServer({
|
|
480
519
|
server: { middlewareMode: true },
|
|
481
520
|
appType: 'custom',
|
|
482
521
|
});
|
|
483
|
-
|
|
522
|
+
template = fs.readFileSync(path.join(__dirname, 'index.html'), 'utf-8');
|
|
484
523
|
} else {
|
|
485
|
-
|
|
524
|
+
template = fs.readFileSync(path.join(DIST_DIR, 'client/index.html'), 'utf-8');
|
|
486
525
|
}
|
|
487
526
|
|
|
488
|
-
|
|
489
|
-
|
|
527
|
+
const server = http.createServer(async (req, res) => {
|
|
528
|
+
const url = req.url || '/';
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
if (!isProduction && url.startsWith('/@')) {
|
|
532
|
+
// Vite dev server requests
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Static assets
|
|
537
|
+
if (url.startsWith('/assets/') || url.endsWith('.js') || url.endsWith('.css')) {
|
|
538
|
+
const filePath = isProduction
|
|
539
|
+
? path.join(DIST_DIR, 'client', url)
|
|
540
|
+
: path.join(__dirname, url);
|
|
541
|
+
|
|
542
|
+
if (fs.existsSync(filePath)) {
|
|
543
|
+
const ext = path.extname(filePath);
|
|
544
|
+
const contentType = ext === '.css' ? 'text/css' : 'application/javascript';
|
|
545
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
546
|
+
res.end(fs.readFileSync(filePath));
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// SSR rendering
|
|
552
|
+
const html = await renderPage({
|
|
553
|
+
url,
|
|
554
|
+
template,
|
|
555
|
+
manifest: isProduction
|
|
556
|
+
? JSON.parse(fs.readFileSync(path.join(DIST_DIR, 'client/ssr-manifest.json'), 'utf-8'))
|
|
557
|
+
: undefined
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
561
|
+
res.end(html);
|
|
562
|
+
} catch (err: any) {
|
|
563
|
+
if (!isProduction && vite) {
|
|
564
|
+
vite.ssrFixStacktrace(err);
|
|
565
|
+
}
|
|
566
|
+
console.error('SSR Error:', err);
|
|
567
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
568
|
+
res.end('Internal Server Error');
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
server.listen(PORT, () => {
|
|
573
|
+
console.log(\`LytJS SSR server running at http://localhost:\${PORT}\`);
|
|
574
|
+
console.log(\`Mode: \${isProduction ? 'Production' : 'Development'}\`);
|
|
575
|
+
});
|
|
490
576
|
}
|
|
491
577
|
|
|
492
|
-
createServer();
|
|
578
|
+
createServer().catch(console.error);
|
|
493
579
|
`;
|
|
494
580
|
writeFile(join(targetDir, "server.ts"), serverTs);
|
|
495
581
|
}
|
|
@@ -666,12 +752,13 @@ defineEmits<{
|
|
|
666
752
|
}];
|
|
667
753
|
},
|
|
668
754
|
page(name, basePath) {
|
|
755
|
+
const pascalName = toPascalCase(name);
|
|
669
756
|
const filePath = join(basePath, `${name}.lyt`);
|
|
670
757
|
return [{
|
|
671
758
|
filePath,
|
|
672
759
|
content: `<template>
|
|
673
760
|
<div class="page-${name}">
|
|
674
|
-
<h1>${
|
|
761
|
+
<h1>${pascalName}</h1>
|
|
675
762
|
</div>
|
|
676
763
|
</template>
|
|
677
764
|
|
|
@@ -722,6 +809,157 @@ export const use${toPascalCase(name)}Store = defineStore('${name}', () => {
|
|
|
722
809
|
reset,
|
|
723
810
|
};
|
|
724
811
|
});
|
|
812
|
+
`
|
|
813
|
+
}];
|
|
814
|
+
},
|
|
815
|
+
directive(name, basePath) {
|
|
816
|
+
const filePath = join(basePath, `${name}.ts`);
|
|
817
|
+
const camelCaseName = toCamelCase(name);
|
|
818
|
+
return [{
|
|
819
|
+
filePath,
|
|
820
|
+
content: `import type { Directive } from '@lytjs/core';
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* ${toPascalCase(name)} Directive
|
|
824
|
+
*
|
|
825
|
+
* @example
|
|
826
|
+
* \`\`\`vue
|
|
827
|
+
* <div v-${camelCaseName} />
|
|
828
|
+
* \`\`\`
|
|
829
|
+
*/
|
|
830
|
+
export const v${toPascalCase(name)}: Directive = {
|
|
831
|
+
mounted(el, binding) {
|
|
832
|
+
// Directive mounted
|
|
833
|
+
},
|
|
834
|
+
|
|
835
|
+
updated(el, binding) {
|
|
836
|
+
// Directive updated
|
|
837
|
+
},
|
|
838
|
+
|
|
839
|
+
unmounted(el) {
|
|
840
|
+
// Directive unmounted
|
|
841
|
+
},
|
|
842
|
+
};
|
|
843
|
+
`
|
|
844
|
+
}];
|
|
845
|
+
},
|
|
846
|
+
composable(name, basePath) {
|
|
847
|
+
const filePath = join(basePath, `use${toPascalCase(name)}.ts`);
|
|
848
|
+
return [{
|
|
849
|
+
filePath,
|
|
850
|
+
content: `import { signal, computed } from '@lytjs/reactivity';
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* ${toPascalCase(name)} Composable
|
|
854
|
+
*
|
|
855
|
+
* @example
|
|
856
|
+
* \`\`\`typescript
|
|
857
|
+
* const { state, actions } = use${toPascalCase(name)}();
|
|
858
|
+
* \`\`\`
|
|
859
|
+
*/
|
|
860
|
+
export function use${toPascalCase(name)}() {
|
|
861
|
+
// State
|
|
862
|
+
const isLoading = signal(false);
|
|
863
|
+
const error = signal<Error | null>(null);
|
|
864
|
+
const data = signal<any>(null);
|
|
865
|
+
|
|
866
|
+
// Computed
|
|
867
|
+
const hasData = computed(() => data.value !== null);
|
|
868
|
+
|
|
869
|
+
// Actions
|
|
870
|
+
async function fetch() {
|
|
871
|
+
isLoading.value = true;
|
|
872
|
+
error.value = null;
|
|
873
|
+
try {
|
|
874
|
+
// TODO: Fetch logic here
|
|
875
|
+
// data.value = await someApi();
|
|
876
|
+
} catch (e) {
|
|
877
|
+
error.value = e as Error;
|
|
878
|
+
} finally {
|
|
879
|
+
isLoading.value = false;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function reset() {
|
|
884
|
+
isLoading.value = false;
|
|
885
|
+
error.value = null;
|
|
886
|
+
data.value = null;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return {
|
|
890
|
+
isLoading,
|
|
891
|
+
error,
|
|
892
|
+
data,
|
|
893
|
+
hasData,
|
|
894
|
+
fetch,
|
|
895
|
+
reset,
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
`
|
|
899
|
+
}];
|
|
900
|
+
},
|
|
901
|
+
hook(name, basePath) {
|
|
902
|
+
const filePath = join(basePath, `use${toPascalCase(name)}.ts`);
|
|
903
|
+
return [{
|
|
904
|
+
filePath,
|
|
905
|
+
content: `import { signal, onMounted, onUnmounted } from '@lytjs/core';
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* ${toPascalCase(name)} Hook
|
|
909
|
+
*/
|
|
910
|
+
export function use${toPascalCase(name)}() {
|
|
911
|
+
const state = signal(null);
|
|
912
|
+
|
|
913
|
+
onMounted(() => {
|
|
914
|
+
// Setup code on mount
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
onUnmounted(() => {
|
|
918
|
+
// Cleanup on unmount
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
return {
|
|
922
|
+
state,
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
`
|
|
926
|
+
}];
|
|
927
|
+
},
|
|
928
|
+
util(name, basePath) {
|
|
929
|
+
const filePath = join(basePath, `${name}.ts`);
|
|
930
|
+
return [{
|
|
931
|
+
filePath,
|
|
932
|
+
content: `/**
|
|
933
|
+
* ${toPascalCase(name)} Utility Functions
|
|
934
|
+
*/
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* ${toPascalCase(name)} function
|
|
938
|
+
*
|
|
939
|
+
* @param input - The input value
|
|
940
|
+
* @returns The processed result
|
|
941
|
+
*/
|
|
942
|
+
export function ${toCamelCase(name)}(input: any) {
|
|
943
|
+
// TODO: Implement function
|
|
944
|
+
return input;
|
|
945
|
+
}
|
|
946
|
+
`
|
|
947
|
+
}];
|
|
948
|
+
},
|
|
949
|
+
middleware(name, basePath) {
|
|
950
|
+
const filePath = join(basePath, `${name}.ts`);
|
|
951
|
+
return [{
|
|
952
|
+
filePath,
|
|
953
|
+
content: `import type { NavigationGuard } from '@lytjs/router';
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* ${toPascalCase(name)} Middleware
|
|
957
|
+
*/
|
|
958
|
+
export const ${toCamelCase(name)}Middleware: NavigationGuard = (to, from, next) => {
|
|
959
|
+
// Middleware logic
|
|
960
|
+
console.log('Middleware:', to.path);
|
|
961
|
+
next();
|
|
962
|
+
};
|
|
725
963
|
`
|
|
726
964
|
}];
|
|
727
965
|
}
|
|
@@ -729,6 +967,10 @@ export const use${toPascalCase(name)}Store = defineStore('${name}', () => {
|
|
|
729
967
|
function toPascalCase(str) {
|
|
730
968
|
return str.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
731
969
|
}
|
|
970
|
+
function toCamelCase(str) {
|
|
971
|
+
const pascalCase = toPascalCase(str);
|
|
972
|
+
return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
|
|
973
|
+
}
|
|
732
974
|
function resolveTargetDir(type) {
|
|
733
975
|
const cwd = process.cwd();
|
|
734
976
|
switch (type) {
|
|
@@ -738,6 +980,16 @@ function resolveTargetDir(type) {
|
|
|
738
980
|
return join(cwd, "src", "pages");
|
|
739
981
|
case "store":
|
|
740
982
|
return join(cwd, "src", "stores");
|
|
983
|
+
case "directive":
|
|
984
|
+
return join(cwd, "src", "directives");
|
|
985
|
+
case "composable":
|
|
986
|
+
return join(cwd, "src", "composables");
|
|
987
|
+
case "util":
|
|
988
|
+
return join(cwd, "src", "utils");
|
|
989
|
+
case "middleware":
|
|
990
|
+
return join(cwd, "src", "middleware");
|
|
991
|
+
case "hook":
|
|
992
|
+
return join(cwd, "src", "hooks");
|
|
741
993
|
}
|
|
742
994
|
}
|
|
743
995
|
async function add(type, name, options = {}) {
|
|
@@ -764,6 +1016,548 @@ async function add(type, name, options = {}) {
|
|
|
764
1016
|
logger.success(`Created ${type}: ${file.filePath}`);
|
|
765
1017
|
}
|
|
766
1018
|
}
|
|
1019
|
+
var TEMPLATES3 = {
|
|
1020
|
+
component: (data, withStyles, withTest, template, lang) => {
|
|
1021
|
+
const styleImport = withStyles ? `
|
|
1022
|
+
import './${data.kebabName}.styles.css';` : "";
|
|
1023
|
+
const tsOnly = lang === "ts";
|
|
1024
|
+
if (template === "sfc") {
|
|
1025
|
+
return `<template>
|
|
1026
|
+
<div class="${data.kebabName}">
|
|
1027
|
+
<slot>
|
|
1028
|
+
${data.pascalName} Component
|
|
1029
|
+
</slot>
|
|
1030
|
+
</div>
|
|
1031
|
+
</template>
|
|
1032
|
+
|
|
1033
|
+
<script setup${tsOnly ? ' lang="ts"' : ""}>
|
|
1034
|
+
${tsOnly ? `import { ref } from '@lytjs/reactivity';
|
|
1035
|
+
` : ""}
|
|
1036
|
+
${tsOnly ? `
|
|
1037
|
+
export interface ${data.pascalName}Props {
|
|
1038
|
+
className?: string;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const props = defineProps<${data.pascalName}Props>();
|
|
1042
|
+
` : ""}
|
|
1043
|
+
|
|
1044
|
+
const title = ref('${data.pascalName}');
|
|
1045
|
+
</script>
|
|
1046
|
+
|
|
1047
|
+
<style scoped>
|
|
1048
|
+
.${data.kebabName} {
|
|
1049
|
+
/* Component styles */
|
|
1050
|
+
}
|
|
1051
|
+
</style>
|
|
1052
|
+
`;
|
|
1053
|
+
}
|
|
1054
|
+
const testImport = withTest ? `
|
|
1055
|
+
import { describe, it, expect } from 'vitest';
|
|
1056
|
+
import { ${data.pascalName} } from './${data.kebabName}';
|
|
1057
|
+
|
|
1058
|
+
describe('${data.pascalName}', () => {
|
|
1059
|
+
it('should render', () => {
|
|
1060
|
+
// Add test here
|
|
1061
|
+
expect(true).toBe(true);
|
|
1062
|
+
});
|
|
1063
|
+
});` : "";
|
|
1064
|
+
const propsDecl = tsOnly ? `['className', 'children']` : `[]`;
|
|
1065
|
+
return `/**
|
|
1066
|
+
* ${data.pascalName} \u7EC4\u4EF6
|
|
1067
|
+
*
|
|
1068
|
+
* @description ${data.description}
|
|
1069
|
+
* @created ${data.date}
|
|
1070
|
+
*/
|
|
1071
|
+
|
|
1072
|
+
import { h, defineComponent } from '@lytjs/core';${styleImport}
|
|
1073
|
+
|
|
1074
|
+
${tsOnly ? `export interface ${data.pascalName}Props {
|
|
1075
|
+
className?: string;
|
|
1076
|
+
children?: any;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
` : ""}${template === "functional" ? `export function ${data.pascalName}(${tsOnly ? `props: ${data.pascalName}Props` : "props"}) {
|
|
1080
|
+
const { className = '', children } = props;
|
|
1081
|
+
|
|
1082
|
+
return (
|
|
1083
|
+
<div className={\`${data.kebabName} \${className}\`}>
|
|
1084
|
+
{children || '${data.pascalName} Component'}
|
|
1085
|
+
</div>
|
|
1086
|
+
);
|
|
1087
|
+
}` : `export const ${data.pascalName} = defineComponent({
|
|
1088
|
+
name: '${data.pascalName}',
|
|
1089
|
+
props: ${propsDecl},
|
|
1090
|
+
setup(props) {
|
|
1091
|
+
const { className = '', children } = props;
|
|
1092
|
+
|
|
1093
|
+
return () => (
|
|
1094
|
+
<div className={\`${data.kebabName} \${className}\`}>
|
|
1095
|
+
{children || '${data.pascalName} Component'}
|
|
1096
|
+
</div>
|
|
1097
|
+
);
|
|
1098
|
+
},
|
|
1099
|
+
});`}
|
|
1100
|
+
|
|
1101
|
+
export default ${data.pascalName};${testImport}
|
|
1102
|
+
`;
|
|
1103
|
+
},
|
|
1104
|
+
page: (data, withStyles, withTest, template, lang) => {
|
|
1105
|
+
const styleImport = withStyles ? `
|
|
1106
|
+
import './${data.kebabName}.styles.css';` : "";
|
|
1107
|
+
const tsOnly = lang === "ts";
|
|
1108
|
+
if (template === "sfc") {
|
|
1109
|
+
return `<template>
|
|
1110
|
+
<div class="${data.kebabName}-page">
|
|
1111
|
+
<h1>{title}</h1>
|
|
1112
|
+
<p>Page content for ${data.pascalName}</p>
|
|
1113
|
+
<slot />
|
|
1114
|
+
</div>
|
|
1115
|
+
</template>
|
|
1116
|
+
|
|
1117
|
+
<script setup${tsOnly ? ' lang="ts"' : ""}>
|
|
1118
|
+
${tsOnly ? `import { ref } from '@lytjs/reactivity';
|
|
1119
|
+
` : ""}
|
|
1120
|
+
${tsOnly ? `
|
|
1121
|
+
export interface ${data.pascalName}PageProps {
|
|
1122
|
+
title?: string;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const props = defineProps<${data.pascalName}PageProps>();
|
|
1126
|
+
` : ""}
|
|
1127
|
+
|
|
1128
|
+
const title = ref(props.title || '${data.pascalName}');
|
|
1129
|
+
</script>
|
|
1130
|
+
|
|
1131
|
+
<style scoped>
|
|
1132
|
+
.${data.kebabName}-page {
|
|
1133
|
+
padding: 2rem;
|
|
1134
|
+
}
|
|
1135
|
+
</style>
|
|
1136
|
+
`;
|
|
1137
|
+
}
|
|
1138
|
+
const testImport = withTest ? `
|
|
1139
|
+
import { describe, it, expect } from 'vitest';
|
|
1140
|
+
import { ${data.pascalName}Page } from './${data.kebabName}';
|
|
1141
|
+
|
|
1142
|
+
describe('${data.pascalName}Page', () => {
|
|
1143
|
+
it('should render', () => {
|
|
1144
|
+
// Add test here
|
|
1145
|
+
expect(true).toBe(true);
|
|
1146
|
+
});
|
|
1147
|
+
});` : "";
|
|
1148
|
+
return `/**
|
|
1149
|
+
* ${data.pascalName} \u9875\u9762
|
|
1150
|
+
*
|
|
1151
|
+
* @description ${data.description}
|
|
1152
|
+
* @created ${data.date}
|
|
1153
|
+
*/
|
|
1154
|
+
|
|
1155
|
+
import { h, ${tsOnly ? "signal" : "signal"} } from '@lytjs/core';
|
|
1156
|
+
${styleImport}
|
|
1157
|
+
|
|
1158
|
+
${tsOnly ? `export interface ${data.pascalName}PageProps {
|
|
1159
|
+
title?: string;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
` : ""}export function ${data.pascalName}Page(${tsOnly ? `props: ${data.pascalName}PageProps` : "props"}) {
|
|
1163
|
+
const { title = '${data.pascalName}' } = props;
|
|
1164
|
+
|
|
1165
|
+
return (
|
|
1166
|
+
<div className="${data.kebabName}-page">
|
|
1167
|
+
<h1>{title}</h1>
|
|
1168
|
+
<p>Page content for ${data.pascalName}</p>
|
|
1169
|
+
</div>
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
export default ${data.pascalName}Page;${testImport}
|
|
1174
|
+
`;
|
|
1175
|
+
},
|
|
1176
|
+
service: (data, _withStyles, _withTest, _template, lang) => {
|
|
1177
|
+
const tsOnly = lang === "ts";
|
|
1178
|
+
return `/**
|
|
1179
|
+
* ${data.pascalName} \u670D\u52A1
|
|
1180
|
+
*
|
|
1181
|
+
* @description ${data.description}
|
|
1182
|
+
* @created ${data.date}
|
|
1183
|
+
*/
|
|
1184
|
+
|
|
1185
|
+
${tsOnly ? `export interface ${data.pascalName}ServiceOptions {
|
|
1186
|
+
baseUrl?: string;
|
|
1187
|
+
timeout?: number;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
` : ""}${tsOnly ? `export class ${data.pascalName}Service {
|
|
1191
|
+
private baseUrl: string;
|
|
1192
|
+
private timeout: number;
|
|
1193
|
+
` : `export class ${data.pascalName}Service {
|
|
1194
|
+
`}
|
|
1195
|
+
constructor(${tsOnly ? `options: ${data.pascalName}ServiceOptions = {}` : "options = {}"}) {
|
|
1196
|
+
this.baseUrl = options.baseUrl || '/api';
|
|
1197
|
+
this.timeout = options.timeout || 30000;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
async getAll()${tsOnly ? ": Promise<any[]>" : ""} {
|
|
1201
|
+
const response = await fetch(\`\${this.baseUrl}/${data.kebabName}s\`, {
|
|
1202
|
+
method: 'GET',
|
|
1203
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1204
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
1205
|
+
});
|
|
1206
|
+
return response.json();
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
async getById(id)${tsOnly ? ": Promise<any>" : ""} {
|
|
1210
|
+
const response = await fetch(\`\${this.baseUrl}/${data.kebabName}s/\${id}\`, {
|
|
1211
|
+
method: 'GET',
|
|
1212
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1213
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
1214
|
+
});
|
|
1215
|
+
return response.json();
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
async create(${tsOnly ? "data: any" : "data"})${tsOnly ? ": Promise<any>" : ""} {
|
|
1219
|
+
const response = await fetch(\`\${this.baseUrl}/${data.kebabName}s\`, {
|
|
1220
|
+
method: 'POST',
|
|
1221
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1222
|
+
body: JSON.stringify(data),
|
|
1223
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
1224
|
+
});
|
|
1225
|
+
return response.json();
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
async update(id)${tsOnly ? ": Promise<any>" : ""} {
|
|
1229
|
+
const response = await fetch(\`\${this.baseUrl}/${data.kebabName}s/\${id}\`, {
|
|
1230
|
+
method: 'PUT',
|
|
1231
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1232
|
+
body: JSON.stringify(data),
|
|
1233
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
1234
|
+
});
|
|
1235
|
+
return response.json();
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
async delete(id)${tsOnly ? ": Promise<void>" : ""} {
|
|
1239
|
+
await fetch(\`\${this.baseUrl}/${data.kebabName}s/\${id}\`, {
|
|
1240
|
+
method: 'DELETE',
|
|
1241
|
+
signal: AbortSignal.timeout(this.timeout),
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
export default ${data.pascalName}Service;
|
|
1247
|
+
`;
|
|
1248
|
+
},
|
|
1249
|
+
hook: (data, _withStyles, _withTest, _template, lang) => {
|
|
1250
|
+
const tsOnly = lang === "ts";
|
|
1251
|
+
return `/**
|
|
1252
|
+
* ${data.pascalName} Hook
|
|
1253
|
+
*
|
|
1254
|
+
* @description ${data.description}
|
|
1255
|
+
* @created ${data.date}
|
|
1256
|
+
*/
|
|
1257
|
+
|
|
1258
|
+
import { signal, effect } from '@lytjs/reactivity';
|
|
1259
|
+
|
|
1260
|
+
${tsOnly ? `export interface ${data.pascalName}Options {
|
|
1261
|
+
immediate?: boolean;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
export interface ${data.pascalName}Return {
|
|
1265
|
+
data: ReturnType<typeof signal>;
|
|
1266
|
+
loading: ReturnType<typeof signal>;
|
|
1267
|
+
error: ReturnType<typeof signal>;
|
|
1268
|
+
execute: () => Promise<void>;
|
|
1269
|
+
reset: () => void;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
` : ""}export function use${data.pascalName}(${tsOnly ? `options: ${data.pascalName}Options = {}` : "options = {}"})${tsOnly ? `: ${data.pascalName}Return` : ""} {
|
|
1273
|
+
const { immediate = false } = options;
|
|
1274
|
+
|
|
1275
|
+
const data = signal<any>(null);
|
|
1276
|
+
const loading = signal(false);
|
|
1277
|
+
const error = signal<Error | null>(null);
|
|
1278
|
+
|
|
1279
|
+
async function execute() {
|
|
1280
|
+
loading.value = true;
|
|
1281
|
+
error.value = null;
|
|
1282
|
+
|
|
1283
|
+
try {
|
|
1284
|
+
const result = await new Promise(resolve => setTimeout(() => resolve(null), 100));
|
|
1285
|
+
data.value = result;
|
|
1286
|
+
} catch (e) {
|
|
1287
|
+
error.value = e as Error;
|
|
1288
|
+
} finally {
|
|
1289
|
+
loading.value = false;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
function reset() {
|
|
1294
|
+
data.value = null;
|
|
1295
|
+
loading.value = false;
|
|
1296
|
+
error.value = null;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (immediate) {
|
|
1300
|
+
execute();
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
return {
|
|
1304
|
+
data,
|
|
1305
|
+
loading,
|
|
1306
|
+
error,
|
|
1307
|
+
execute,
|
|
1308
|
+
reset,
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
export default use${data.pascalName};
|
|
1313
|
+
`;
|
|
1314
|
+
},
|
|
1315
|
+
store: (data, _withStyles, _withTest, _template, lang) => {
|
|
1316
|
+
const tsOnly = lang === "ts";
|
|
1317
|
+
return `/**
|
|
1318
|
+
* ${data.pascalName} Store
|
|
1319
|
+
*
|
|
1320
|
+
* @description ${data.description}
|
|
1321
|
+
* @created ${data.date}
|
|
1322
|
+
*/
|
|
1323
|
+
|
|
1324
|
+
import { signal, computed } from '@lytjs/reactivity';
|
|
1325
|
+
|
|
1326
|
+
${tsOnly ? `export interface ${data.pascalName}State {
|
|
1327
|
+
items: any[];
|
|
1328
|
+
selectedId: string | null;
|
|
1329
|
+
loading: boolean;
|
|
1330
|
+
error: Error | null;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
` : ""}export function create${data.pascalName}Store() {
|
|
1334
|
+
const state = signal${tsOnly ? `<${data.pascalName}State>` : ""}({
|
|
1335
|
+
items: [],
|
|
1336
|
+
selectedId: null,
|
|
1337
|
+
loading: false,
|
|
1338
|
+
error: null,
|
|
1339
|
+
});
|
|
1340
|
+
|
|
1341
|
+
const selectedItem = computed(() => {
|
|
1342
|
+
const currentState = state.value;
|
|
1343
|
+
return currentState.items.find(item => item.id === currentState.selectedId);
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
const itemCount = computed(() => state.value.items.length);
|
|
1347
|
+
|
|
1348
|
+
function setItems(items) {
|
|
1349
|
+
state.value = { ...state.value, items };
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
function selectItem(id) {
|
|
1353
|
+
state.value = { ...state.value, selectedId: id };
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function addItem(item) {
|
|
1357
|
+
state.value = {
|
|
1358
|
+
...state.value,
|
|
1359
|
+
items: [...state.value.items, item],
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
function updateItem(id, updates) {
|
|
1364
|
+
state.value = {
|
|
1365
|
+
...state.value,
|
|
1366
|
+
items: state.value.items.map(item =>
|
|
1367
|
+
item.id === id ? { ...item, ...updates } : item
|
|
1368
|
+
),
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
function removeItem(id) {
|
|
1373
|
+
state.value = {
|
|
1374
|
+
...state.value,
|
|
1375
|
+
items: state.value.items.filter(item => item.id !== id),
|
|
1376
|
+
selectedId: state.value.selectedId === id ? null : state.value.selectedId,
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
function setLoading(loading) {
|
|
1381
|
+
state.value = { ...state.value, loading };
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
function setError(error) {
|
|
1385
|
+
state.value = { ...state.value, error };
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
function reset() {
|
|
1389
|
+
state.value = {
|
|
1390
|
+
items: [],
|
|
1391
|
+
selectedId: null,
|
|
1392
|
+
loading: false,
|
|
1393
|
+
error: null,
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
return {
|
|
1398
|
+
state,
|
|
1399
|
+
selectedItem,
|
|
1400
|
+
itemCount,
|
|
1401
|
+
setItems,
|
|
1402
|
+
selectItem,
|
|
1403
|
+
addItem,
|
|
1404
|
+
updateItem,
|
|
1405
|
+
removeItem,
|
|
1406
|
+
setLoading,
|
|
1407
|
+
setError,
|
|
1408
|
+
reset,
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
${tsOnly ? `export type ${data.pascalName}Store = ReturnType<typeof create${data.pascalName}Store>;
|
|
1413
|
+
` : ""}export default create${data.pascalName}Store;
|
|
1414
|
+
`;
|
|
1415
|
+
},
|
|
1416
|
+
layout: (data, withStyles, _withTest, _template, lang) => {
|
|
1417
|
+
const tsOnly = lang === "ts";
|
|
1418
|
+
const styleImport = withStyles ? `
|
|
1419
|
+
import './${data.kebabName}.styles.css';` : "";
|
|
1420
|
+
return `/**
|
|
1421
|
+
* ${data.pascalName} \u5E03\u5C40
|
|
1422
|
+
*
|
|
1423
|
+
* @description ${data.description}
|
|
1424
|
+
* @created ${data.date}
|
|
1425
|
+
*/
|
|
1426
|
+
|
|
1427
|
+
import { h, defineComponent } from '@lytjs/core';${styleImport}
|
|
1428
|
+
|
|
1429
|
+
${tsOnly ? `export interface ${data.pascalName}LayoutProps {
|
|
1430
|
+
children?: any;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
` : ""}export const ${data.pascalName}Layout = defineComponent({
|
|
1434
|
+
name: '${data.pascalName}Layout',
|
|
1435
|
+
setup(props) {
|
|
1436
|
+
return () => (
|
|
1437
|
+
<div className="${data.kebabName}-layout">
|
|
1438
|
+
<header className="${data.kebabName}-header">
|
|
1439
|
+
<slot name="header">
|
|
1440
|
+
<h1>${data.pascalName}</h1>
|
|
1441
|
+
</slot>
|
|
1442
|
+
</header>
|
|
1443
|
+
<main className="${data.kebabName}-main">
|
|
1444
|
+
<slot />
|
|
1445
|
+
</main>
|
|
1446
|
+
<footer className="${data.kebabName}-footer">
|
|
1447
|
+
<slot name="footer" />
|
|
1448
|
+
</footer>
|
|
1449
|
+
</div>
|
|
1450
|
+
);
|
|
1451
|
+
},
|
|
1452
|
+
});
|
|
1453
|
+
|
|
1454
|
+
export default ${data.pascalName}Layout;
|
|
1455
|
+
`;
|
|
1456
|
+
},
|
|
1457
|
+
middleware: (data, _withStyles, _withTest, _template, lang) => {
|
|
1458
|
+
const tsOnly = lang === "ts";
|
|
1459
|
+
return `/**
|
|
1460
|
+
* ${data.pascalName} \u4E2D\u95F4\u4EF6
|
|
1461
|
+
*
|
|
1462
|
+
* @description ${data.description}
|
|
1463
|
+
* @created ${data.date}
|
|
1464
|
+
*/
|
|
1465
|
+
|
|
1466
|
+
${tsOnly ? `import type { Request, Response, NextFunction } from 'express';
|
|
1467
|
+
` : ""}
|
|
1468
|
+
export function ${data.camelName}Middleware(${tsOnly ? `req: Request, res: Response, next: NextFunction` : "req, res, next"}) {
|
|
1469
|
+
try {
|
|
1470
|
+
console.log('[${data.pascalName}] Middleware executed');
|
|
1471
|
+
next();
|
|
1472
|
+
} catch (error) {
|
|
1473
|
+
next(error);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
export default ${data.camelName}Middleware;
|
|
1478
|
+
`;
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
function toPascalCase2(name) {
|
|
1482
|
+
return name.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
1483
|
+
}
|
|
1484
|
+
function toCamelCase2(name) {
|
|
1485
|
+
const pascal = toPascalCase2(name);
|
|
1486
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
1487
|
+
}
|
|
1488
|
+
function toKebabCase(name) {
|
|
1489
|
+
return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
1490
|
+
}
|
|
1491
|
+
async function generate(options) {
|
|
1492
|
+
const {
|
|
1493
|
+
type,
|
|
1494
|
+
name,
|
|
1495
|
+
path: basePath = "./src",
|
|
1496
|
+
withStyles = false,
|
|
1497
|
+
withTest = false,
|
|
1498
|
+
description = "",
|
|
1499
|
+
template = "default",
|
|
1500
|
+
language = "ts"
|
|
1501
|
+
} = options;
|
|
1502
|
+
const templateData = {
|
|
1503
|
+
name,
|
|
1504
|
+
pascalName: toPascalCase2(name),
|
|
1505
|
+
kebabName: toKebabCase(name),
|
|
1506
|
+
camelName: toCamelCase2(name),
|
|
1507
|
+
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
1508
|
+
description: description || `${toPascalCase2(name)} ${type}`
|
|
1509
|
+
};
|
|
1510
|
+
const typeDirs = {
|
|
1511
|
+
component: "components",
|
|
1512
|
+
page: "pages",
|
|
1513
|
+
service: "services",
|
|
1514
|
+
hook: "hooks",
|
|
1515
|
+
store: "stores",
|
|
1516
|
+
layout: "layouts",
|
|
1517
|
+
middleware: "middleware"
|
|
1518
|
+
};
|
|
1519
|
+
const targetDir = path.join(
|
|
1520
|
+
process.cwd(),
|
|
1521
|
+
basePath,
|
|
1522
|
+
typeDirs[type] || "components"
|
|
1523
|
+
);
|
|
1524
|
+
await ensureDir(targetDir);
|
|
1525
|
+
const templateFn = TEMPLATES3[type];
|
|
1526
|
+
if (!templateFn) {
|
|
1527
|
+
logger.error(`Unknown type: ${type}`);
|
|
1528
|
+
logger.info("Available types: component, page, service, hook, store, layout, middleware");
|
|
1529
|
+
process.exit(1);
|
|
1530
|
+
}
|
|
1531
|
+
const extension = template === "sfc" ? "lyt" : language;
|
|
1532
|
+
const filename = `${templateData.kebabName}${type === "page" ? ".page" : ""}.${extension}`;
|
|
1533
|
+
const filePath = path.join(targetDir, filename);
|
|
1534
|
+
const content = templateFn(templateData, withStyles, withTest, template, language);
|
|
1535
|
+
await writeFile(filePath, content);
|
|
1536
|
+
logger.success(`Generated ${type}: ${filePath}`);
|
|
1537
|
+
if (withStyles && template !== "sfc") {
|
|
1538
|
+
const styleContent = `/**
|
|
1539
|
+
* ${templateData.pascalName} Styles
|
|
1540
|
+
*/
|
|
1541
|
+
|
|
1542
|
+
.${templateData.kebabName} {
|
|
1543
|
+
/* Component styles */
|
|
1544
|
+
}
|
|
1545
|
+
`;
|
|
1546
|
+
const stylePath = path.join(targetDir, `${templateData.kebabName}.styles.css`);
|
|
1547
|
+
await writeFile(stylePath, styleContent);
|
|
1548
|
+
logger.success(`Generated styles: ${stylePath}`);
|
|
1549
|
+
}
|
|
1550
|
+
if (withTest && template !== "sfc") {
|
|
1551
|
+
logger.info("Test file included in generated component");
|
|
1552
|
+
}
|
|
1553
|
+
logger.info("\nNext steps:");
|
|
1554
|
+
logger.info(` cd ${targetDir}`);
|
|
1555
|
+
logger.info(` Import your ${type}: import { ${template === "sfc" ? "default" : templateData.pascalName} } from './${templateData.kebabName}'`);
|
|
1556
|
+
logger.info("\nAvailable options:");
|
|
1557
|
+
logger.info(" --template=sfc : Single File Component (.lyt)");
|
|
1558
|
+
logger.info(" --template=functional : Functional component");
|
|
1559
|
+
logger.info(" --language=js : JavaScript output");
|
|
1560
|
+
}
|
|
767
1561
|
var PLUGIN_TEMPLATES = {
|
|
768
1562
|
default: "Default plugin template with TypeScript",
|
|
769
1563
|
minimal: "Minimal plugin without extra dependencies",
|
|
@@ -855,8 +1649,6 @@ const optionsSchema: ConfigSchema<${pluginName.replace(/-/g, "")}Options> = {
|
|
|
855
1649
|
additionalProperties: false,
|
|
856
1650
|
};
|
|
857
1651
|
|
|
858
|
-
${pluginName.replace(/-/g, "")}Options\`;
|
|
859
|
-
|
|
860
1652
|
export interface ${pluginName.replace(/-/g, "")}Options {
|
|
861
1653
|
debug?: boolean;
|
|
862
1654
|
option1?: string;
|
|
@@ -1174,8 +1966,10 @@ async function runCli(rawArgs = process.argv.slice(2)) {
|
|
|
1174
1966
|
});
|
|
1175
1967
|
break;
|
|
1176
1968
|
case "add":
|
|
1177
|
-
|
|
1178
|
-
|
|
1969
|
+
const addTypes = ["component", "page", "store", "directive", "composable", "util", "middleware", "hook"];
|
|
1970
|
+
if (!args[0] || !addTypes.includes(args[0])) {
|
|
1971
|
+
logger.error("Usage: lyt add <type> <name>");
|
|
1972
|
+
logger.info("Types: component, page, store, directive, composable, util, middleware, hook");
|
|
1179
1973
|
logger.info("Example: lyt add component Button");
|
|
1180
1974
|
process.exit(1);
|
|
1181
1975
|
}
|
|
@@ -1183,6 +1977,24 @@ async function runCli(rawArgs = process.argv.slice(2)) {
|
|
|
1183
1977
|
force: options.force
|
|
1184
1978
|
});
|
|
1185
1979
|
break;
|
|
1980
|
+
case "generate":
|
|
1981
|
+
case "g":
|
|
1982
|
+
const genTypes = ["component", "page", "service", "hook", "store"];
|
|
1983
|
+
if (!args[0] || !genTypes.includes(args[0])) {
|
|
1984
|
+
logger.error("Usage: lyt generate <type> <name>");
|
|
1985
|
+
logger.info("Types: component, page, service, hook, store");
|
|
1986
|
+
logger.info("Example: lyt generate component Button");
|
|
1987
|
+
process.exit(1);
|
|
1988
|
+
}
|
|
1989
|
+
await generate({
|
|
1990
|
+
type: args[0],
|
|
1991
|
+
name: args[1] || "Unnamed",
|
|
1992
|
+
path: options.path,
|
|
1993
|
+
withStyles: options.styles,
|
|
1994
|
+
withTest: options.test,
|
|
1995
|
+
withStorybook: options.storybook
|
|
1996
|
+
});
|
|
1997
|
+
break;
|
|
1186
1998
|
case "plugin":
|
|
1187
1999
|
if (!args[0]) {
|
|
1188
2000
|
logger.error("Usage: lyt plugin <create|build|validate|templates>");
|
|
@@ -1278,10 +2090,11 @@ ${logger.bold("Commands:")}
|
|
|
1278
2090
|
dev Start development server
|
|
1279
2091
|
build Build for production
|
|
1280
2092
|
test Run tests
|
|
1281
|
-
add <type> <name> Generate a component, page,
|
|
2093
|
+
add <type> <name> Generate a component, page, store, directive, composable, etc.
|
|
2094
|
+
generate, g Advanced code generation (component, page, service, hook, store)
|
|
1282
2095
|
plugin <subcmd> Plugin development commands
|
|
1283
2096
|
help Show this help message
|
|
1284
|
-
|
|
2097
|
+
|
|
1285
2098
|
${logger.bold("Options:")}
|
|
1286
2099
|
--version, -v Show version number
|
|
1287
2100
|
--help Show help
|
|
@@ -1305,6 +2118,12 @@ ${logger.bold("Test Options:")}
|
|
|
1305
2118
|
--coverage Generate coverage report
|
|
1306
2119
|
--grep <pattern> Filter tests by pattern
|
|
1307
2120
|
|
|
2121
|
+
${logger.bold("Generate Options:")}
|
|
2122
|
+
--path <dir> Output directory (default: ./src)
|
|
2123
|
+
--styles Generate CSS styles file
|
|
2124
|
+
--test Generate test file
|
|
2125
|
+
--storybook Generate Storybook story file
|
|
2126
|
+
|
|
1308
2127
|
${logger.bold("Plugin Options:")}
|
|
1309
2128
|
--template <name> Use a specific plugin template (default, minimal, withConfig)
|
|
1310
2129
|
--force Overwrite existing directory
|
|
@@ -1325,6 +2144,16 @@ ${logger.bold("Examples:")}
|
|
|
1325
2144
|
lyt add component Button
|
|
1326
2145
|
lyt add page About
|
|
1327
2146
|
lyt add store user
|
|
2147
|
+
lyt directive click-outside
|
|
2148
|
+
lyt add composable fetch-data
|
|
2149
|
+
lyt add util format
|
|
2150
|
+
lyt add hook window-size
|
|
2151
|
+
lyt generate component Button --styles --test
|
|
2152
|
+
lyt generate page Dashboard --path ./src/pages
|
|
2153
|
+
lyt generate service User --path ./src/services
|
|
2154
|
+
lyt generate hook useCounter
|
|
2155
|
+
lyt generate store Auth --path ./src/stores
|
|
2156
|
+
lyt g page Login
|
|
1328
2157
|
lyt plugin create my-plugin
|
|
1329
2158
|
lyt plugin create my-plugin --template withConfig
|
|
1330
2159
|
lyt plugin build
|
|
@@ -1337,6 +2166,6 @@ if (__require.main === module) {
|
|
|
1337
2166
|
runCli().catch(console.error);
|
|
1338
2167
|
}
|
|
1339
2168
|
|
|
1340
|
-
export { add, build, buildPlugin, create, createPlugin, detectPackageManager, dev, ensureDir, exists, getAddCommand, getInstallCommand, getRunCommand, listPluginTemplates, listTemplates, logger, readFile, runCli, test, validatePlugin, writeFile };
|
|
2169
|
+
export { add, build, buildPlugin, create, createPlugin, detectPackageManager, dev, ensureDir, exists, generate, getAddCommand, getInstallCommand, getRunCommand, listPluginTemplates, listTemplates, logger, readFile, runCli, test, validatePlugin, writeFile };
|
|
1341
2170
|
//# sourceMappingURL=index.mjs.map
|
|
1342
2171
|
//# sourceMappingURL=index.mjs.map
|