@loom-framework/core 0.1.0-alpha.142 → 0.1.0-alpha.143
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/adapters/base.d.ts +31 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +69 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/factory.d.ts +8 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +25 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/filesystem.d.ts +46 -0
- package/dist/adapters/filesystem.d.ts.map +1 -0
- package/dist/adapters/filesystem.js +321 -0
- package/dist/adapters/filesystem.js.map +1 -0
- package/dist/adapters/index.d.ts +10 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +8 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +37 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +264 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/backend/index.js +1 -1
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/routes/skills.d.ts +3 -3
- package/dist/backend/routes/skills.d.ts.map +1 -1
- package/dist/backend/routes/skills.js +3 -3
- package/dist/backend/routes/skills.js.map +1 -1
- package/dist/backend/services/skill-archive.d.ts +13 -0
- package/dist/backend/services/skill-archive.d.ts.map +1 -0
- package/dist/backend/services/skill-archive.js +84 -0
- package/dist/backend/services/skill-archive.js.map +1 -0
- package/dist/backend/services/skill-parser.d.ts +41 -0
- package/dist/backend/services/skill-parser.d.ts.map +1 -0
- package/dist/backend/services/skill-parser.js +184 -0
- package/dist/backend/services/skill-parser.js.map +1 -0
- package/dist/backend/services/skill-service.d.ts +113 -0
- package/dist/backend/services/skill-service.d.ts.map +1 -0
- package/dist/backend/services/skill-service.js +265 -0
- package/dist/backend/services/skill-service.js.map +1 -0
- package/dist/cli/commands/data.js +2 -2
- package/dist/cli/commands/data.js.map +1 -1
- package/dist/cli/commands/generate-dashboard.d.ts.map +1 -1
- package/dist/cli/commands/generate-dashboard.js +1 -450
- package/dist/cli/commands/generate-dashboard.js.map +1 -1
- package/dist/cli/commands/generate-page.d.ts.map +1 -1
- package/dist/cli/commands/generate-page.js +4 -436
- package/dist/cli/commands/generate-page.js.map +1 -1
- package/dist/cli/commands/serve.d.ts +12 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +43 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/framework.d.ts +28 -0
- package/dist/cli/framework.d.ts.map +1 -0
- package/dist/cli/framework.js +29 -0
- package/dist/cli/framework.js.map +1 -0
- package/dist/cli/helpers/i18n-template.d.ts +13 -0
- package/dist/cli/helpers/i18n-template.d.ts.map +1 -0
- package/dist/cli/helpers/i18n-template.js +48 -0
- package/dist/cli/helpers/i18n-template.js.map +1 -0
- package/dist/cli/templates/crud-page.d.ts +14 -0
- package/dist/cli/templates/crud-page.d.ts.map +1 -0
- package/dist/cli/templates/crud-page.js +405 -0
- package/dist/cli/templates/crud-page.js.map +1 -0
- package/dist/cli/templates/dashboard-page.d.ts +11 -0
- package/dist/cli/templates/dashboard-page.d.ts.map +1 -0
- package/dist/cli/templates/dashboard-page.js +456 -0
- package/dist/cli/templates/dashboard-page.js.map +1 -0
- package/dist/cli/templates/index.d.ts +2 -0
- package/dist/cli/templates/index.d.ts.map +1 -1
- package/dist/cli/templates/index.js +2 -0
- package/dist/cli/templates/index.js.map +1 -1
- package/dist/config.d.ts +22 -22
- package/dist/dashboard-config.d.ts +10 -10
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,447 +7,15 @@
|
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import { promises as fs } from 'fs';
|
|
9
9
|
import path from 'path';
|
|
10
|
-
import { loadConfig } from '../../config.js';
|
|
11
|
-
import { getModelSchema } from '../../config.js';
|
|
10
|
+
import { loadConfig, getModelSchema } from '../../config.js';
|
|
12
11
|
import { generateCapabilities } from '../generators/capability-generator.js';
|
|
13
12
|
import { resolveLocale } from '../../types/locale.js';
|
|
14
13
|
import { resolveProjectRoot } from '../utils.js';
|
|
15
14
|
import { toPascalCase } from '../helpers/naming.js';
|
|
16
|
-
import {
|
|
17
|
-
import { generateTagColors, generateColumns, buildLabel } from '../helpers/column-template.js';
|
|
15
|
+
import { buildLabel } from '../helpers/column-template.js';
|
|
18
16
|
import { wireAppTsxAutomatic, wireSystemSettingsPage } from '../helpers/app-tsx-wiring.js';
|
|
19
17
|
import { backupFile } from '../helpers/backup.js';
|
|
20
|
-
|
|
21
|
-
function i18nKey(modelName) {
|
|
22
|
-
return `model.${modelName}`;
|
|
23
|
-
}
|
|
24
|
-
/** Generate registerMessages() calls for a model's LocaleString fields */
|
|
25
|
-
function generateRegisterMessages(model, relations) {
|
|
26
|
-
const prefix = i18nKey(model.name);
|
|
27
|
-
const zhMessages = {};
|
|
28
|
-
const enMessages = {};
|
|
29
|
-
// Model title
|
|
30
|
-
zhMessages[`${prefix}.title`] = resolveLocale(model.description, 'zh-CN') || toPascalCase(model.name);
|
|
31
|
-
enMessages[`${prefix}.title`] = resolveLocale(model.description, 'en-US') || toPascalCase(model.name);
|
|
32
|
-
// Field labels
|
|
33
|
-
for (const f of model.fields) {
|
|
34
|
-
if (f.name === 'id')
|
|
35
|
-
continue;
|
|
36
|
-
const key = `${prefix}.field.${f.name}`;
|
|
37
|
-
zhMessages[key] = resolveLocale(f.description, 'zh-CN') || f.name;
|
|
38
|
-
enMessages[key] = resolveLocale(f.description, 'en-US') || f.name;
|
|
39
|
-
}
|
|
40
|
-
// Enum labels (for Tag display)
|
|
41
|
-
for (const f of model.fields) {
|
|
42
|
-
if (!f.enumLabels)
|
|
43
|
-
continue;
|
|
44
|
-
for (const [enumVal, localeMap] of Object.entries(f.enumLabels)) {
|
|
45
|
-
const key = `${prefix}.enum.${f.name}.${enumVal}`;
|
|
46
|
-
zhMessages[key] = localeMap['zh-CN'] || enumVal;
|
|
47
|
-
enMessages[key] = localeMap['en-US'] || enumVal;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// Relation labels
|
|
51
|
-
for (const r of (relations?.filter(r => r.from === model.name) ?? [])) {
|
|
52
|
-
const key = `${prefix}.relation.${r.name}`;
|
|
53
|
-
zhMessages[key] = resolveLocale(r.label, 'zh-CN') || r.name;
|
|
54
|
-
enMessages[key] = resolveLocale(r.label, 'en-US') || r.name;
|
|
55
|
-
}
|
|
56
|
-
return `registerMessages('zh-CN', ${JSON.stringify(zhMessages)});
|
|
57
|
-
registerMessages('en-US', ${JSON.stringify(enMessages)});`;
|
|
58
|
-
}
|
|
59
|
-
/** Generate CRUD page template from model schema */
|
|
60
|
-
function crudPageTemplate(model, aiButtons, relations) {
|
|
61
|
-
const pascalName = toPascalCase(model.name);
|
|
62
|
-
const recordType = `${pascalName}Record`;
|
|
63
|
-
const modelRelations = relations?.filter(r => r.from === model.name) ?? [];
|
|
64
|
-
const hasRelations = modelRelations.length > 0;
|
|
65
|
-
// Resolve CRUD config (all default to true)
|
|
66
|
-
const crud = model.crud ?? {};
|
|
67
|
-
const hasExport = crud.export !== false;
|
|
68
|
-
const hasImport = crud.import !== false;
|
|
69
|
-
const hasDeleteWithUndo = crud.deleteWithUndo !== false;
|
|
70
|
-
// Detect field types for conditional logic
|
|
71
|
-
const dateFields = model.fields.filter(f => f.type === 'date').map(f => f.name);
|
|
72
|
-
const hasDateFields = dateFields.length > 0;
|
|
73
|
-
// Build TypeScript interface from fields
|
|
74
|
-
const fieldDefs = model.fields.map((f) => {
|
|
75
|
-
const tsType = f.type === 'string[]' ? 'string[]'
|
|
76
|
-
: f.type === 'number[]' ? 'number[]'
|
|
77
|
-
: f.type === 'json' ? 'Record<string, unknown>'
|
|
78
|
-
: f.type === 'number' ? 'number'
|
|
79
|
-
: f.type === 'boolean' ? 'boolean'
|
|
80
|
-
: f.type === 'date' ? 'string'
|
|
81
|
-
: 'string';
|
|
82
|
-
return ` ${f.name}${f.required ? '' : '?'}: ${tsType};`;
|
|
83
|
-
}).join('\n');
|
|
84
|
-
const columns = generateColumns(model.fields, model.name, aiButtons, true);
|
|
85
|
-
const formItems = model.fields
|
|
86
|
-
.filter((f) => f.name !== 'id') // id is auto-generated
|
|
87
|
-
.map((f) => fieldToFormItem(f, model.name, true))
|
|
88
|
-
.join('\n');
|
|
89
|
-
// Generate handleEdit with date conversion
|
|
90
|
-
const handleEditBody = hasDateFields
|
|
91
|
-
? `const handleEdit = (record: ${recordType}) => {
|
|
92
|
-
setEditingRecord(record);
|
|
93
|
-
const formValues = { ...record };
|
|
94
|
-
${dateFields.map(f => ` if (formValues.${f}) formValues.${f} = dayjs(formValues.${f}) as any;`).join('\n')}
|
|
95
|
-
form.setFieldsValue(formValues);
|
|
96
|
-
setModalOpen(true);
|
|
97
|
-
};`
|
|
98
|
-
: `const handleEdit = (record: ${recordType}) => {
|
|
99
|
-
setEditingRecord(record);
|
|
100
|
-
form.setFieldsValue(record);
|
|
101
|
-
setModalOpen(true);
|
|
102
|
-
};`;
|
|
103
|
-
// Generate handleSave with date serialization
|
|
104
|
-
const handleSaveBody = hasDateFields
|
|
105
|
-
? `const handleSave = async () => {
|
|
106
|
-
try {
|
|
107
|
-
const values = await form.validateFields();
|
|
108
|
-
${dateFields.map(f => ` if (values.${f}) values.${f} = values.${f}.format('YYYY-MM-DD');`).join('\n')}
|
|
109
|
-
if (editingRecord?.id) {
|
|
110
|
-
await update(editingRecord.id, values);
|
|
111
|
-
message.success(t('crud.updateSuccess'));
|
|
112
|
-
} else {
|
|
113
|
-
await create(values);
|
|
114
|
-
message.success(t('crud.createSuccess'));
|
|
115
|
-
}
|
|
116
|
-
setModalOpen(false);
|
|
117
|
-
fetchData();
|
|
118
|
-
} catch {
|
|
119
|
-
// form validation failed
|
|
120
|
-
}
|
|
121
|
-
};`
|
|
122
|
-
: `const handleSave = async () => {
|
|
123
|
-
try {
|
|
124
|
-
const values = await form.validateFields();
|
|
125
|
-
if (editingRecord?.id) {
|
|
126
|
-
await update(editingRecord.id, values);
|
|
127
|
-
message.success(t('crud.updateSuccess'));
|
|
128
|
-
} else {
|
|
129
|
-
await create(values);
|
|
130
|
-
message.success(t('crud.createSuccess'));
|
|
131
|
-
}
|
|
132
|
-
setModalOpen(false);
|
|
133
|
-
fetchData();
|
|
134
|
-
} catch {
|
|
135
|
-
// form validation failed
|
|
136
|
-
}
|
|
137
|
-
};`;
|
|
138
|
-
const dayjsImport = hasDateFields ? `\nimport dayjs from 'dayjs';` : '';
|
|
139
|
-
// With useSchema, AI buttons come dynamically, so always include AI imports
|
|
140
|
-
const hasAIButtons = true; // always true with useSchema — AI buttons loaded at runtime
|
|
141
|
-
// Build imports — useSchema + filterOptions/selectOptions always included
|
|
142
|
-
const antdExtra = ', Dropdown';
|
|
143
|
-
const iconsExtra = ', ThunderboltOutlined';
|
|
144
|
-
const extraIcons = ', EditOutlined, DeleteOutlined';
|
|
145
|
-
const loomExtra = ', AIContext, useLocale, registerMessages, enumLabel, useAppShell';
|
|
146
|
-
const reactExtra = ', useContext, useEffect';
|
|
147
|
-
// Conditional imports based on CRUD config
|
|
148
|
-
const antdUpload = hasImport ? ', Upload' : '';
|
|
149
|
-
const iconsDownload = hasExport ? ', DownloadOutlined' : '';
|
|
150
|
-
const iconsUpload = hasImport ? ', UploadOutlined' : '';
|
|
151
|
-
const useDataExtra = `${hasExport ? ', exportCsv' : ''}${hasImport ? ', importCsv' : ''}`;
|
|
152
|
-
const i18nRegistration = generateRegisterMessages(model, relations);
|
|
153
|
-
const titleKey = `model.${model.name}.title`;
|
|
154
|
-
// Import modal template
|
|
155
|
-
const importModalTemplate = hasImport ? `
|
|
156
|
-
<Modal
|
|
157
|
-
title={t('crud.importTitle')}
|
|
158
|
-
open={importModalOpen}
|
|
159
|
-
onCancel={() => setImportModalOpen(false)}
|
|
160
|
-
footer={null}
|
|
161
|
-
width={480}
|
|
162
|
-
>
|
|
163
|
-
<Upload.Dragger
|
|
164
|
-
accept=".csv"
|
|
165
|
-
showUploadList={false}
|
|
166
|
-
beforeUpload={(file) => {
|
|
167
|
-
const reader = new FileReader();
|
|
168
|
-
reader.onload = async (e) => {
|
|
169
|
-
const text = e.target?.result as string;
|
|
170
|
-
try {
|
|
171
|
-
const result = await importCsv(text);
|
|
172
|
-
message.success(\`\${t('crud.importSuccess')}: \${result.imported}\`);
|
|
173
|
-
if (result.errors.length > 0) {
|
|
174
|
-
message.warning(result.errors.join('; '));
|
|
175
|
-
}
|
|
176
|
-
fetchData();
|
|
177
|
-
} catch {
|
|
178
|
-
message.error(t('crud.importFailed'));
|
|
179
|
-
}
|
|
180
|
-
setImportModalOpen(false);
|
|
181
|
-
};
|
|
182
|
-
reader.readAsText(file);
|
|
183
|
-
return false;
|
|
184
|
-
}}
|
|
185
|
-
>
|
|
186
|
-
<p className="ant-upload-drag-icon"><UploadOutlined /></p>
|
|
187
|
-
<p>{t('crud.importDrag')}</p>
|
|
188
|
-
</Upload.Dragger>
|
|
189
|
-
<div style={{ marginTop: 12, textAlign: 'center' }}>
|
|
190
|
-
<Button size="small" type="link" onClick={handleDownloadTemplate}>{t('crud.downloadTemplate')}</Button>
|
|
191
|
-
</div>
|
|
192
|
-
</Modal>` : '';
|
|
193
|
-
// Header action buttons
|
|
194
|
-
const headerButtons = [
|
|
195
|
-
hasExport ? `<Button icon={<DownloadOutlined />} onClick={() => exportCsv()}>{t('crud.export')}</Button>` : '',
|
|
196
|
-
hasImport ? `<Button icon={<UploadOutlined />} onClick={() => setImportModalOpen(true)}>{t('crud.import')}</Button>` : '',
|
|
197
|
-
`<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
|
198
|
-
{t('crud.add')}
|
|
199
|
-
</Button>`,
|
|
200
|
-
].filter(Boolean).join('\n ');
|
|
201
|
-
return `import React, { useState, useCallback${reactExtra} } from 'react';
|
|
202
|
-
import { Table, Button, Modal, Form, Input, InputNumber, Select, Switch, DatePicker, Space, message, Tag, Card, Flex, Tooltip, Typography${antdUpload}, Drawer, Breadcrumb, type TableProps${antdExtra} } from 'antd';
|
|
203
|
-
import { PlusOutlined${iconsDownload}${iconsUpload}, EyeOutlined, HomeOutlined${iconsExtra}${extraIcons} } from '@ant-design/icons';
|
|
204
|
-
import { useData, useSchema, filterOptions, selectOptions${loomExtra} } from '@loom-framework/frontend-antd';${dayjsImport}${hasRelations ? "\nimport { RelationPanel } from '@loom-framework/frontend-antd';" : ''}
|
|
205
|
-
|
|
206
|
-
${i18nRegistration}
|
|
207
|
-
|
|
208
|
-
interface ${recordType} {
|
|
209
|
-
id: string;
|
|
210
|
-
${fieldDefs}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const modelFields: { name: string; type: string }[] = [
|
|
214
|
-
${model.fields.map(f => ` { name: '${f.name}', type: '${f.type}' },`).join('\n')}
|
|
215
|
-
];
|
|
216
|
-
|
|
217
|
-
export function ${pascalName}Page(): React.ReactElement {
|
|
218
|
-
const { t } = useLocale();
|
|
219
|
-
const { breadcrumbs, onNavClick } = useAppShell();
|
|
220
|
-
const { list, total, create, update, remove, loading, refresh${useDataExtra} } = useData<${recordType}>('${model.name}', { skipInitialFetch: true });
|
|
221
|
-
const { schema } = useSchema('${model.name}');
|
|
222
|
-
const [form] = Form.useForm();
|
|
223
|
-
const [modalOpen, setModalOpen] = useState(false);
|
|
224
|
-
const [editingRecord, setEditingRecord] = useState<${recordType} | null>(null);
|
|
225
|
-
const [tableFilters, setTableFilters] = useState<Record<string, any>>({});
|
|
226
|
-
const [tableSorter, setTableSorter] = useState<{ field: string; order: 'ascend' | 'descend' | null }>({ field: '', order: null });
|
|
227
|
-
const [currentPage, setCurrentPage] = useState(1);
|
|
228
|
-
const [pageSize, setPageSize] = useState(10);
|
|
229
|
-
const [importModalOpen, setImportModalOpen] = useState(false);${hasImport ? '' : ' // only used when import is enabled'}
|
|
230
|
-
const [detailRecord, setDetailRecord] = useState<${recordType} | null>(null);
|
|
231
|
-
|
|
232
|
-
const handleDownloadTemplate = () => {
|
|
233
|
-
const headers = ['${model.fields.filter(f => f.name !== 'id').map(f => f.name).join("','")}'];
|
|
234
|
-
const csv = headers.join(',');
|
|
235
|
-
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
|
|
236
|
-
const url = URL.createObjectURL(blob);
|
|
237
|
-
const a = document.createElement('a');
|
|
238
|
-
a.href = url;
|
|
239
|
-
a.download = '${model.name}_template.csv';
|
|
240
|
-
a.click();
|
|
241
|
-
URL.revokeObjectURL(url);
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const fetchData = useCallback((filters?: Record<string, (string | number | boolean | null)[] | null>, sorter?: { field: string; order: 'ascend' | 'descend' | null }, page?: number, size?: number) => {
|
|
245
|
-
const currentFilters = filters ?? tableFilters;
|
|
246
|
-
const currentSorter = sorter ?? tableSorter;
|
|
247
|
-
const fetchPage = page ?? currentPage;
|
|
248
|
-
const fetchSize = size ?? pageSize;
|
|
249
|
-
const queryParams: any = {};
|
|
250
|
-
// Build filter from antd column filter values
|
|
251
|
-
const apiFilter: Record<string, unknown> = {};
|
|
252
|
-
for (const [key, val] of Object.entries(currentFilters)) {
|
|
253
|
-
if (val && val.length > 0) {
|
|
254
|
-
const field = modelFields.find(f => f.name === key);
|
|
255
|
-
if (field?.type === 'date') {
|
|
256
|
-
// Date range: val is [dayjs, dayjs] stored in filter
|
|
257
|
-
apiFilter[key] = { __range: val.map((v: any) => v?.format?.('YYYY-MM-DD') || v) };
|
|
258
|
-
} else if (val.length === 1) {
|
|
259
|
-
apiFilter[key] = val[0];
|
|
260
|
-
} else {
|
|
261
|
-
// Multiple filter values for a single column (e.g. subject in [数学, 英语])
|
|
262
|
-
apiFilter[key] = val;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (Object.keys(apiFilter).length > 0) queryParams.filter = apiFilter;
|
|
267
|
-
// Build sort
|
|
268
|
-
if (currentSorter.field && currentSorter.order) {
|
|
269
|
-
queryParams.sort = currentSorter.field;
|
|
270
|
-
queryParams.sortOrder = currentSorter.order === 'descend' ? 'desc' : 'asc';
|
|
271
|
-
}
|
|
272
|
-
// Server-side pagination
|
|
273
|
-
queryParams.limit = fetchSize;
|
|
274
|
-
queryParams.offset = (fetchPage - 1) * fetchSize;
|
|
275
|
-
refresh(queryParams);
|
|
276
|
-
}, [refresh, tableFilters, tableSorter, currentPage, pageSize]);
|
|
277
|
-
|
|
278
|
-
// Initial fetch with pagination (useEffect with empty deps, fetchData is stable via useCallback)
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
fetchData(undefined, undefined, 1, 10);
|
|
281
|
-
}, []);
|
|
282
|
-
|
|
283
|
-
const handleAdd = () => {
|
|
284
|
-
setEditingRecord(null);
|
|
285
|
-
form.resetFields();
|
|
286
|
-
setModalOpen(true);
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
${handleEditBody}
|
|
290
|
-
|
|
291
|
-
const handleDelete = async (record: ${recordType}) => {
|
|
292
|
-
${hasDeleteWithUndo ? `const snapshot = { ...record };
|
|
293
|
-
try {
|
|
294
|
-
await remove(record.id);
|
|
295
|
-
fetchData();
|
|
296
|
-
message.info({
|
|
297
|
-
content: t('crud.deleted'),
|
|
298
|
-
duration: 5,
|
|
299
|
-
btn: <Button size="small" type="link" onClick={() => { create(snapshot); fetchData(); message.destroy(); }}>{t('common.undo')}</Button>,
|
|
300
|
-
});
|
|
301
|
-
} catch {
|
|
302
|
-
message.error(t('crud.deleteFailed'));
|
|
303
|
-
}` : `Modal.confirm({
|
|
304
|
-
title: t('crud.deleteConfirm'),
|
|
305
|
-
onOk: async () => {
|
|
306
|
-
try {
|
|
307
|
-
await remove(record.id);
|
|
308
|
-
message.success(t('crud.deleted'));
|
|
309
|
-
fetchData();
|
|
310
|
-
} catch {
|
|
311
|
-
message.error(t('crud.deleteFailed'));
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
});`}
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
${handleSaveBody}
|
|
318
|
-
|
|
319
|
-
const ai = useContext(AIContext);
|
|
320
|
-
|
|
321
|
-
// AI buttons from schema (dynamic via useSchema)
|
|
322
|
-
const aiButtonMenuItems = (record: ${recordType}) => {
|
|
323
|
-
const ctx: Record<string, string | string[] | number | boolean> = {};
|
|
324
|
-
for (const [k, v] of Object.entries(record)) {
|
|
325
|
-
if (Array.isArray(v) && v.length === 0) continue;
|
|
326
|
-
// null/undefined → "" so {{var}} resolves to empty string instead of "Missing"
|
|
327
|
-
ctx[k] = (v ?? '') as string | string[] | number | boolean;
|
|
328
|
-
}
|
|
329
|
-
const buttons = schema?.aiButtons ?? [];
|
|
330
|
-
return buttons.map(btn => ({
|
|
331
|
-
key: btn.id,
|
|
332
|
-
label: btn.label,
|
|
333
|
-
onClick: () => ai?.triggerAI({ buttonId: btn.id, label: btn.label, prompt: btn.prompt, context: ctx }),
|
|
334
|
-
}));
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
const columns: TableProps<${recordType}>['columns'] = [
|
|
338
|
-
${columns}
|
|
339
|
-
];${hasRelations ? `
|
|
340
|
-
// Add detail button to action column for relations
|
|
341
|
-
if (columns.length > 0) {
|
|
342
|
-
const lastCol = columns[columns.length - 1] as any;
|
|
343
|
-
if (lastCol?.render) {
|
|
344
|
-
const originalRender = lastCol.render;
|
|
345
|
-
lastCol.render = (_: unknown, record: ${recordType}) => {
|
|
346
|
-
const original = originalRender(_, record);
|
|
347
|
-
return (
|
|
348
|
-
<Space>
|
|
349
|
-
{original}
|
|
350
|
-
<Tooltip title={t('crud.detail')}><Button type="text" size="small" icon={<EyeOutlined />} onClick={() => setDetailRecord(record)} /></Tooltip>
|
|
351
|
-
</Space>
|
|
352
|
-
);
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
lastCol.width = ${hasAIButtons && hasRelations ? 160 : hasAIButtons ? 120 : hasRelations ? 120 : 90};
|
|
356
|
-
}` : ''}
|
|
357
|
-
${generateTagColors(model.fields)}
|
|
358
|
-
const handleTableChange: TableProps<${recordType}>['onChange'] = (pagination, filters, sorter) => {
|
|
359
|
-
const newFilters = filters as Record<string, any>;
|
|
360
|
-
const newSorter = !Array.isArray(sorter) && sorter.field
|
|
361
|
-
? { field: sorter.field as string, order: sorter.order as 'ascend' | 'descend' | null }
|
|
362
|
-
: { field: '', order: null };
|
|
363
|
-
const newPage = pagination.current || 1;
|
|
364
|
-
const newSize = pagination.pageSize || 10;
|
|
365
|
-
setTableFilters(newFilters);
|
|
366
|
-
setTableSorter(newSorter);
|
|
367
|
-
setCurrentPage(newPage);
|
|
368
|
-
setPageSize(newSize);
|
|
369
|
-
fetchData(newFilters, newSorter, newPage, newSize);
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
return (
|
|
373
|
-
<>
|
|
374
|
-
<div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
|
|
375
|
-
<Flex justify="space-between" align="center" style={{ marginBottom: 12 }}>
|
|
376
|
-
<Breadcrumb items={[{ title: <HomeOutlined onClick={() => onNavClick?.('')} style={{ cursor: 'pointer' }} /> }, ...(breadcrumbs || []).map(b => ({ title: b.path ? <a onClick={() => onNavClick?.(b.path!)}>{b.title}</a> : b.title }))] /**/} />
|
|
377
|
-
<Space>
|
|
378
|
-
${headerButtons}
|
|
379
|
-
</Space>
|
|
380
|
-
</Flex>
|
|
381
|
-
|
|
382
|
-
<Table
|
|
383
|
-
columns={columns}
|
|
384
|
-
dataSource={list}
|
|
385
|
-
rowKey="id"
|
|
386
|
-
loading={loading}
|
|
387
|
-
size="middle"
|
|
388
|
-
scroll={{ x: 'max-content', y: 'calc(100vh - 280px)' }}
|
|
389
|
-
onChange={handleTableChange}
|
|
390
|
-
pagination={{ current: currentPage, pageSize, total, showSizeChanger: true, showTotal: (count) => t('crud.total', { total: count }) }}
|
|
391
|
-
/>${hasRelations ? `
|
|
392
|
-
<Drawer
|
|
393
|
-
title={detailRecord ? \`\${t('crud.detail')}: \${detailRecord.id}\` : ''}
|
|
394
|
-
open={!!detailRecord}
|
|
395
|
-
onClose={() => setDetailRecord(null)}
|
|
396
|
-
width={640}
|
|
397
|
-
>
|
|
398
|
-
{detailRecord && (
|
|
399
|
-
<RelationPanel
|
|
400
|
-
model='${model.name}'
|
|
401
|
-
recordId={detailRecord.id}
|
|
402
|
-
relations={[
|
|
403
|
-
${modelRelations.map(r => {
|
|
404
|
-
const labelKey = `model.${model.name}.relation.${r.name}`;
|
|
405
|
-
return `{ name: '${r.name}', label: t('${labelKey}'), from: '${r.from}', to: '${r.to}', foreignKey: '${r.foreignKey}', type: '${r.type}'${r.through ? `, through: '${r.through}'` : ''} }`;
|
|
406
|
-
}).join(',\n ')}
|
|
407
|
-
]}
|
|
408
|
-
/>
|
|
409
|
-
)}
|
|
410
|
-
</Drawer>` : ''}
|
|
411
|
-
</div>
|
|
412
|
-
|
|
413
|
-
<Modal
|
|
414
|
-
title={editingRecord ? \`\${t('crud.edit')}\${t('${titleKey}')}\` : \`\${t('crud.add')}\${t('${titleKey}')}\`}
|
|
415
|
-
open={modalOpen}
|
|
416
|
-
onOk={handleSave}
|
|
417
|
-
onCancel={() => setModalOpen(false)}
|
|
418
|
-
destroyOnHidden
|
|
419
|
-
width={640}
|
|
420
|
-
>
|
|
421
|
-
<Form form={form} layout="vertical">
|
|
422
|
-
${formItems}
|
|
423
|
-
</Form>
|
|
424
|
-
</Modal>
|
|
425
|
-
${importModalTemplate}
|
|
426
|
-
</>
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
export default ${pascalName}Page;
|
|
431
|
-
`;
|
|
432
|
-
}
|
|
433
|
-
/** Minimal skeleton page template (no model) */
|
|
434
|
-
const SKELETON_TEMPLATE = (pascalName) => `import React from 'react';
|
|
435
|
-
|
|
436
|
-
export interface ${pascalName}Props {
|
|
437
|
-
// TODO: Define page props
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
export function ${pascalName}(props: ${pascalName}Props): React.ReactElement {
|
|
441
|
-
return (
|
|
442
|
-
<div className="${pascalName.toLowerCase()}-page">
|
|
443
|
-
<h1>${pascalName}</h1>
|
|
444
|
-
<p>TODO: Implement this page.</p>
|
|
445
|
-
</div>
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
export default ${pascalName};
|
|
450
|
-
`;
|
|
18
|
+
import { crudPageTemplate, skeletonPageTemplate } from '../templates/crud-page.js';
|
|
451
19
|
export function registerGeneratePageCommand(program) {
|
|
452
20
|
program
|
|
453
21
|
.command('page <name>')
|
|
@@ -503,7 +71,7 @@ export function registerGeneratePageCommand(program) {
|
|
|
503
71
|
template = crudPageTemplate(modelSchema, modelAiButtons, config.relations);
|
|
504
72
|
}
|
|
505
73
|
else {
|
|
506
|
-
template =
|
|
74
|
+
template = skeletonPageTemplate(pascalName);
|
|
507
75
|
}
|
|
508
76
|
await fs.mkdir(pageDir, { recursive: true });
|
|
509
77
|
await fs.writeFile(pagePath, template, 'utf-8');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-page.js","sourceRoot":"","sources":["../../../src/cli/commands/generate-page.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate-page.js","sourceRoot":"","sources":["../../../src/cli/commands/generate-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* loom-server CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* loom-server # Serve from current directory
|
|
7
|
+
* loom-server /path/to/project # Serve from specified directory
|
|
8
|
+
* loom-server --port 8080 # Custom port
|
|
9
|
+
* loom-server --host 127.0.0.1 # Custom host
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* loom-server CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* loom-server # Serve from current directory
|
|
7
|
+
* loom-server /path/to/project # Serve from specified directory
|
|
8
|
+
* loom-server --port 8080 # Custom port
|
|
9
|
+
* loom-server --host 127.0.0.1 # Custom host
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
const program = new Command()
|
|
13
|
+
.name('loom-server')
|
|
14
|
+
.description('Start a Loom backend server')
|
|
15
|
+
.argument('[project-root]', 'project root directory', process.cwd())
|
|
16
|
+
.option('-p, --port <number>', 'server port', parseInt)
|
|
17
|
+
.option('-h, --host <string>', 'server host')
|
|
18
|
+
.action(async (projectRoot, options) => {
|
|
19
|
+
const serverConfig = {};
|
|
20
|
+
if (options.port !== undefined)
|
|
21
|
+
serverConfig.port = options.port;
|
|
22
|
+
if (options.host !== undefined)
|
|
23
|
+
serverConfig.host = options.host;
|
|
24
|
+
try {
|
|
25
|
+
const { LoomServer } = await import('../../backend/index.js');
|
|
26
|
+
const server = new LoomServer({
|
|
27
|
+
projectRoot,
|
|
28
|
+
serverConfig,
|
|
29
|
+
});
|
|
30
|
+
await server.initialize();
|
|
31
|
+
await server.start();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof Error && error.message.includes('No loom.config.ts found')) {
|
|
35
|
+
console.error(`Error: No loom.config.ts found in ${projectRoot}`);
|
|
36
|
+
console.error('Create one with: loom init <name>');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
program.parse();
|
|
43
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,6BAA6B,CAAC;KAC1C,QAAQ,CAAC,gBAAgB,EAAE,wBAAwB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KACnE,MAAM,CAAC,qBAAqB,EAAE,aAAa,EAAE,QAAQ,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,WAAmB,EAAE,OAAyC,EAAE,EAAE;IAC/E,MAAM,YAAY,GAA4B,EAAE,CAAC;IACjD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAAE,YAAY,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAAE,YAAY,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;YAC5B,WAAW;YACX,YAAY;SACb,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;YAChF,OAAO,CAAC,KAAK,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command Framework
|
|
3
|
+
*
|
|
4
|
+
* defineCommand() - Type-safe command registration
|
|
5
|
+
* Auto-discovery from cli/commands/ directory
|
|
6
|
+
*/
|
|
7
|
+
import type { CommandDefinition } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Define a CLI command with type safety
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* export default defineCommand({
|
|
14
|
+
* name: 'data:read:users',
|
|
15
|
+
* description: 'Read user records',
|
|
16
|
+
* options: {
|
|
17
|
+
* id: { type: 'string', description: 'User ID' },
|
|
18
|
+
* },
|
|
19
|
+
* async execute(args, context) {
|
|
20
|
+
* const adapter = context.getDataAdapter();
|
|
21
|
+
* const result = await adapter.read('users', { id: args.id as string });
|
|
22
|
+
* return JSON.stringify(result, null, 2);
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function defineCommand(command: CommandDefinition): CommandDefinition;
|
|
28
|
+
//# sourceMappingURL=framework.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../src/cli/framework.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAE3E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command Framework
|
|
3
|
+
*
|
|
4
|
+
* defineCommand() - Type-safe command registration
|
|
5
|
+
* Auto-discovery from cli/commands/ directory
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Define a CLI command with type safety
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* export default defineCommand({
|
|
13
|
+
* name: 'data:read:users',
|
|
14
|
+
* description: 'Read user records',
|
|
15
|
+
* options: {
|
|
16
|
+
* id: { type: 'string', description: 'User ID' },
|
|
17
|
+
* },
|
|
18
|
+
* async execute(args, context) {
|
|
19
|
+
* const adapter = context.getDataAdapter();
|
|
20
|
+
* const result = await adapter.read('users', { id: args.id as string });
|
|
21
|
+
* return JSON.stringify(result, null, 2);
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function defineCommand(command) {
|
|
27
|
+
return command;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=framework.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework.js","sourceRoot":"","sources":["../../src/cli/framework.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAAC,OAA0B;IACtD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* i18n template helpers for page generation
|
|
3
|
+
*
|
|
4
|
+
* Generates registerMessages() calls for model/dashboard LocaleString fields.
|
|
5
|
+
* Shared between CRUD page and Dashboard page generators.
|
|
6
|
+
*/
|
|
7
|
+
import type { ModelSchema } from '../../types/model.js';
|
|
8
|
+
import type { RelationConfig } from '../../types/config.js';
|
|
9
|
+
/** Generate i18n key prefix for a model */
|
|
10
|
+
export declare function i18nKey(modelName: string): string;
|
|
11
|
+
/** Generate registerMessages() calls for a model's LocaleString fields */
|
|
12
|
+
export declare function generateRegisterMessages(model: ModelSchema, relations?: RelationConfig[]): string;
|
|
13
|
+
//# sourceMappingURL=i18n-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n-template.d.ts","sourceRoot":"","sources":["../../../src/cli/helpers/i18n-template.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,2CAA2C;AAC3C,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,cAAc,EAAE,GAAG,MAAM,CAoCjG"}
|