-
Notifications
You must be signed in to change notification settings - Fork 1
/
generate-vue-frontend.js
133 lines (108 loc) · 4.46 KB
/
generate-vue-frontend.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// generate-vue-frontend.js
import analyzeSchema from './db-analyze.js';
import mustache from 'mustache';
import fs from 'fs-extra';
import path from 'path';
import pluralize from 'pluralize';
import ora from 'ora';
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
// Load environment variables
dotenv.config();
// Get the directory name of the current module
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Get the output directory from .env, with a fallback
const outputDir = process.env.FRONTEND_DIR || path.join(__dirname, '..', 'vue-frontend');
// Map SQL data types to JavaScript types
const typeMap = {
int: 'number',
varchar: 'string',
text: 'string',
timestamp: 'Date',
// Add more type mappings as needed
};
function generateComponentName(tableName) {
return pluralize.singular(tableName).charAt(0).toUpperCase() + pluralize.singular(tableName).slice(1);
}
async function generateVueFrontend() {
const spinner = ora('Starting Vue.js frontend generation...').start();
const schema = await analyzeSchema();
spinner.succeed('Schema analysis complete');
// Load Vue component templates
const listTemplate = await fs.readFile('templates/vue/List.vue.mustache', 'utf-8');
const formTemplate = await fs.readFile('templates/vue/Form.vue.mustache', 'utf-8');
const detailTemplate = await fs.readFile('templates/vue/Detail.vue.mustache', 'utf-8');
const apiTemplate = await fs.readFile('templates/vue/api.js.mustache', 'utf-8');
const layoutTemplate = await fs.readFile('templates/vue/Layout.vue.mustache', 'utf-8');
const routerTemplate = await fs.readFile('templates/vue/router.js.mustache', 'utf-8');
const components = [];
for (const tableName in schema) {
if (!schema.hasOwnProperty(tableName)) continue;
const table = schema[tableName];
const componentName = generateComponentName(tableName);
components.push({
name: componentName,
route: tableName.toLowerCase()
});
// Generate List component
const listRendered = mustache.render(listTemplate, {
componentName,
tableName,
columns: table.columns.map(col => ({
name: col.COLUMN_NAME,
label: col.COLUMN_NAME.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
vueBinding: `{{ item.${col.COLUMN_NAME} }}`
}))
});
// Generate Form component
const formRendered = mustache.render(formTemplate, {
componentName,
tableName,
fields: table.columns.map(col => ({
name: col.COLUMN_NAME,
label: col.COLUMN_NAME.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
type: typeMap[col.DATA_TYPE] || 'string'
}))
});
// Generate Detail component
const detailRendered = mustache.render(detailTemplate, {
componentName,
tableName,
fields: table.columns.map(col => ({
name: col.COLUMN_NAME,
label: col.COLUMN_NAME.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
vueBinding: `{{ item.${col.COLUMN_NAME} }}`
}))
});
// Generate API file
const apiRendered = mustache.render(apiTemplate, {
componentName,
tableName
});
// Write files
await fs.outputFile(path.join(outputDir, 'components', `${componentName}List.vue`), listRendered);
await fs.outputFile(path.join(outputDir, 'components', `${componentName}Form.vue`), formRendered);
await fs.outputFile(path.join(outputDir, 'components', `${componentName}Detail.vue`), detailRendered);
await fs.outputFile(path.join(outputDir, 'api', `${componentName.toLowerCase()}Api.js`), apiRendered);
spinner.succeed(`Generated Vue.js components and API for ${tableName}`);
}
// Generate AppLayout component
const layoutRendered = mustache.render(layoutTemplate, {
appName: 'MyApp Demo',
components: components
});
await fs.outputFile(path.join(outputDir, 'components', 'AppLayout.vue'), layoutRendered);
spinner.succeed('Generated AppLayout component');
// Generate main App.vue and router.js
const appTemplate = await fs.readFile('templates/vue/App.vue.mustache', 'utf-8');
const appRendered = mustache.render(appTemplate, {
components: components
});
await fs.outputFile(path.join(outputDir, 'App.vue'), appRendered);
const routerRendered = mustache.render(routerTemplate, {
routes: components
});
await fs.outputFile(path.join(outputDir, 'router.js'), routerRendered);
spinner.succeed("Vue.js frontend generation complete.");
}
export { generateVueFrontend };