@loom-framework/core 0.1.0-alpha.8 → 0.1.0-alpha.80

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.
Files changed (169) hide show
  1. package/dist/adapter-base.d.ts +29 -0
  2. package/dist/adapter-base.d.ts.map +1 -0
  3. package/dist/adapter-base.js +62 -0
  4. package/dist/adapter-base.js.map +1 -0
  5. package/dist/adapter-factory.d.ts +8 -0
  6. package/dist/adapter-factory.d.ts.map +1 -0
  7. package/dist/adapter-factory.js +25 -0
  8. package/dist/adapter-factory.js.map +1 -0
  9. package/dist/adapter-filesystem.d.ts +6 -11
  10. package/dist/adapter-filesystem.d.ts.map +1 -1
  11. package/dist/adapter-filesystem.js +56 -41
  12. package/dist/adapter-filesystem.js.map +1 -1
  13. package/dist/adapter-sqlite.d.ts +6 -23
  14. package/dist/adapter-sqlite.d.ts.map +1 -1
  15. package/dist/adapter-sqlite.js +65 -50
  16. package/dist/adapter-sqlite.js.map +1 -1
  17. package/dist/backend/ai/button-resolver.d.ts +18 -0
  18. package/dist/backend/ai/button-resolver.d.ts.map +1 -0
  19. package/dist/backend/ai/button-resolver.js +58 -0
  20. package/dist/backend/ai/button-resolver.js.map +1 -0
  21. package/dist/backend/ai/engine.d.ts +52 -0
  22. package/dist/backend/ai/engine.d.ts.map +1 -0
  23. package/dist/backend/ai/engine.js +186 -0
  24. package/dist/backend/ai/engine.js.map +1 -0
  25. package/dist/backend/ai/index.d.ts +11 -0
  26. package/dist/backend/ai/index.d.ts.map +1 -0
  27. package/dist/backend/ai/index.js +8 -0
  28. package/dist/backend/ai/index.js.map +1 -0
  29. package/dist/backend/ai/output-parser.d.ts +29 -0
  30. package/dist/backend/ai/output-parser.d.ts.map +1 -0
  31. package/dist/backend/ai/output-parser.js +247 -0
  32. package/dist/backend/ai/output-parser.js.map +1 -0
  33. package/dist/backend/ai/session-manager.d.ts +103 -0
  34. package/dist/backend/ai/session-manager.d.ts.map +1 -0
  35. package/dist/backend/ai/session-manager.js +298 -0
  36. package/dist/backend/ai/session-manager.js.map +1 -0
  37. package/dist/backend/index.d.ts +61 -0
  38. package/dist/backend/index.d.ts.map +1 -0
  39. package/dist/backend/index.js +161 -0
  40. package/dist/backend/index.js.map +1 -0
  41. package/dist/backend/observe/index.d.ts +6 -0
  42. package/dist/backend/observe/index.d.ts.map +1 -0
  43. package/dist/backend/observe/index.js +5 -0
  44. package/dist/backend/observe/index.js.map +1 -0
  45. package/dist/backend/observe/logger.d.ts +28 -0
  46. package/dist/backend/observe/logger.d.ts.map +1 -0
  47. package/dist/backend/observe/logger.js +80 -0
  48. package/dist/backend/observe/logger.js.map +1 -0
  49. package/dist/backend/observe/types.d.ts +26 -0
  50. package/dist/backend/observe/types.d.ts.map +1 -0
  51. package/dist/backend/observe/types.js +7 -0
  52. package/dist/backend/observe/types.js.map +1 -0
  53. package/dist/backend/routes/chat.d.ts +31 -0
  54. package/dist/backend/routes/chat.d.ts.map +1 -0
  55. package/dist/backend/routes/chat.js +426 -0
  56. package/dist/backend/routes/chat.js.map +1 -0
  57. package/dist/backend/routes/data.d.ts +13 -0
  58. package/dist/backend/routes/data.d.ts.map +1 -0
  59. package/dist/backend/routes/data.js +134 -0
  60. package/dist/backend/routes/data.js.map +1 -0
  61. package/dist/backend/routes/health.d.ts +7 -0
  62. package/dist/backend/routes/health.d.ts.map +1 -0
  63. package/dist/backend/routes/health.js +15 -0
  64. package/dist/backend/routes/health.js.map +1 -0
  65. package/dist/backend/routes/index.d.ts +11 -0
  66. package/dist/backend/routes/index.d.ts.map +1 -0
  67. package/dist/backend/routes/index.js +9 -0
  68. package/dist/backend/routes/index.js.map +1 -0
  69. package/dist/backend/routes/skills.d.ts +16 -0
  70. package/dist/backend/routes/skills.d.ts.map +1 -0
  71. package/dist/backend/routes/skills.js +590 -0
  72. package/dist/backend/routes/skills.js.map +1 -0
  73. package/dist/backend/routes/upload.d.ts +24 -0
  74. package/dist/backend/routes/upload.d.ts.map +1 -0
  75. package/dist/backend/routes/upload.js +67 -0
  76. package/dist/backend/routes/upload.js.map +1 -0
  77. package/dist/bin.d.ts +8 -0
  78. package/dist/bin.d.ts.map +1 -0
  79. package/dist/bin.js +12 -0
  80. package/dist/bin.js.map +1 -0
  81. package/dist/capability-generator.d.ts +21 -6
  82. package/dist/capability-generator.d.ts.map +1 -1
  83. package/dist/capability-generator.js +88 -261
  84. package/dist/capability-generator.js.map +1 -1
  85. package/dist/cli/commands/build.d.ts +11 -0
  86. package/dist/cli/commands/build.d.ts.map +1 -0
  87. package/dist/cli/commands/build.js +170 -0
  88. package/dist/cli/commands/build.js.map +1 -0
  89. package/dist/cli/commands/data.d.ts +12 -0
  90. package/dist/cli/commands/data.d.ts.map +1 -0
  91. package/dist/cli/commands/data.js +158 -0
  92. package/dist/cli/commands/data.js.map +1 -0
  93. package/dist/cli/commands/dev.d.ts +9 -0
  94. package/dist/cli/commands/dev.d.ts.map +1 -0
  95. package/dist/cli/commands/dev.js +114 -0
  96. package/dist/cli/commands/dev.js.map +1 -0
  97. package/dist/cli/commands/generate-capabilities.d.ts +8 -0
  98. package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
  99. package/dist/cli/commands/generate-capabilities.js +40 -0
  100. package/dist/cli/commands/generate-capabilities.js.map +1 -0
  101. package/dist/cli/commands/generate-cli-command.d.ts +8 -0
  102. package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
  103. package/dist/cli/commands/generate-cli-command.js +64 -0
  104. package/dist/cli/commands/generate-cli-command.js.map +1 -0
  105. package/dist/cli/commands/generate-page.d.ts +9 -0
  106. package/dist/cli/commands/generate-page.d.ts.map +1 -0
  107. package/dist/cli/commands/generate-page.js +641 -0
  108. package/dist/cli/commands/generate-page.js.map +1 -0
  109. package/dist/cli/commands/generate-skill.d.ts +8 -0
  110. package/dist/cli/commands/generate-skill.d.ts.map +1 -0
  111. package/dist/cli/commands/generate-skill.js +75 -0
  112. package/dist/cli/commands/generate-skill.js.map +1 -0
  113. package/dist/cli/commands/generate.d.ts +6 -0
  114. package/dist/cli/commands/generate.d.ts.map +1 -0
  115. package/dist/cli/commands/generate.js +17 -0
  116. package/dist/cli/commands/generate.js.map +1 -0
  117. package/dist/cli/commands/init.d.ts +8 -0
  118. package/dist/cli/commands/init.d.ts.map +1 -0
  119. package/dist/cli/commands/init.js +539 -0
  120. package/dist/cli/commands/init.js.map +1 -0
  121. package/dist/cli/commands/observe.d.ts +9 -0
  122. package/dist/cli/commands/observe.d.ts.map +1 -0
  123. package/dist/cli/commands/observe.js +142 -0
  124. package/dist/cli/commands/observe.js.map +1 -0
  125. package/dist/cli/commands/skill.d.ts +9 -0
  126. package/dist/cli/commands/skill.d.ts.map +1 -0
  127. package/dist/cli/commands/skill.js +186 -0
  128. package/dist/cli/commands/skill.js.map +1 -0
  129. package/dist/cli/helpers/duration.d.ts +5 -0
  130. package/dist/cli/helpers/duration.d.ts.map +1 -0
  131. package/dist/cli/helpers/duration.js +19 -0
  132. package/dist/cli/helpers/duration.js.map +1 -0
  133. package/dist/cli/helpers/field-template.d.ts +10 -0
  134. package/dist/cli/helpers/field-template.d.ts.map +1 -0
  135. package/dist/cli/helpers/field-template.js +100 -0
  136. package/dist/cli/helpers/field-template.js.map +1 -0
  137. package/dist/cli/helpers/naming.d.ts +12 -0
  138. package/dist/cli/helpers/naming.d.ts.map +1 -0
  139. package/dist/cli/helpers/naming.js +25 -0
  140. package/dist/cli/helpers/naming.js.map +1 -0
  141. package/dist/cli/index.d.ts +9 -0
  142. package/dist/cli/index.d.ts.map +1 -0
  143. package/dist/cli/index.js +33 -0
  144. package/dist/cli/index.js.map +1 -0
  145. package/dist/cli/utils.d.ts +10 -0
  146. package/dist/cli/utils.d.ts.map +1 -0
  147. package/dist/cli/utils.js +31 -0
  148. package/dist/cli/utils.js.map +1 -0
  149. package/dist/config.d.ts +8 -40
  150. package/dist/config.d.ts.map +1 -1
  151. package/dist/config.js +6 -8
  152. package/dist/config.js.map +1 -1
  153. package/dist/index.d.ts +6 -1
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +6 -0
  156. package/dist/index.js.map +1 -1
  157. package/dist/server-bin.d.ts +12 -0
  158. package/dist/server-bin.d.ts.map +1 -0
  159. package/dist/server-bin.js +75 -0
  160. package/dist/server-bin.js.map +1 -0
  161. package/dist/types.d.ts +33 -20
  162. package/dist/types.d.ts.map +1 -1
  163. package/package.json +25 -10
  164. package/templates/app-skill/SKILL.md +27 -0
  165. package/templates/app-skill/references/data-semantics.md +44 -0
  166. package/templates/app-skill/references/models.md +31 -0
  167. package/templates/loom-skill/SKILL.md +140 -0
  168. package/templates/loom-skill/references/README.md +128 -0
  169. package/templates/loom-skill/references/data-model.md +78 -0
@@ -0,0 +1,641 @@
1
+ /**
2
+ * loom generate page <name>
3
+ *
4
+ * With --model: generate capabilities → CRUD page → auto-wire App.tsx
5
+ * Without --model: generate minimal skeleton page
6
+ */
7
+ import chalk from 'chalk';
8
+ import { promises as fs } from 'fs';
9
+ import path from 'path';
10
+ import { loadConfig, getModelSchema, generateCapabilities } from '../../index.js';
11
+ import { resolveProjectRoot } from '../utils.js';
12
+ import { toPascalCase } from '../helpers/naming.js';
13
+ import { fieldToFormItem } from '../helpers/field-template.js';
14
+ /** Semantic color mapping for common enum values */
15
+ const SEMANTIC_COLORS = {
16
+ 'active': 'green', 'inactive': 'default', 'pending': 'orange',
17
+ 'enabled': 'green', 'disabled': 'default',
18
+ '未掌握': 'red', '部分掌握': 'orange', '已掌握': 'green',
19
+ '仍需练习': 'orange',
20
+ '简单': 'green', '中等': 'blue', '困难': 'red',
21
+ 'easy': 'green', 'medium': 'blue', 'hard': 'red',
22
+ 'high': 'red', 'low': 'green',
23
+ '是': 'green', '否': 'red',
24
+ 'yes': 'green', 'no': 'red',
25
+ };
26
+ const TAG_PALETTE = ['blue', 'green', 'orange', 'red', 'purple', 'cyan', 'magenta', 'volcano', 'gold', 'lime'];
27
+ /** Fallback labels for common field names without description */
28
+ const FALLBACK_LABELS = {
29
+ createdAt: '创建时间',
30
+ updatedAt: '更新时间',
31
+ };
32
+ /** Generate tagColors constant code for enum fields */
33
+ function generateTagColors(fields) {
34
+ const enumFields = fields.filter(f => f.enum && f.name !== 'id');
35
+ if (enumFields.length === 0)
36
+ return '';
37
+ const entries = enumFields.map(f => {
38
+ const mappings = f.enum.map((v, i) => {
39
+ const color = SEMANTIC_COLORS[v] || TAG_PALETTE[i % TAG_PALETTE.length];
40
+ return `'${v}': '${color}'`;
41
+ }).join(', ');
42
+ return ` ${f.name}: { ${mappings} }`;
43
+ }).join(',\n');
44
+ return `\nconst tagColors: Record<string, Record<string, string>> = {\n${entries}\n};\n`;
45
+ }
46
+ /** Check if a string field is likely a long-text field */
47
+ function isLongTextField(field) {
48
+ const name = field.name.toLowerCase();
49
+ return (field.type === 'string' &&
50
+ !field.enum &&
51
+ (name.includes('content') ||
52
+ name.includes('description') ||
53
+ name.includes('body') ||
54
+ name.includes('text') ||
55
+ name.includes('note') ||
56
+ name.includes('remark') ||
57
+ name.includes('bio') ||
58
+ name.includes('summary') ||
59
+ name.includes('analysis')));
60
+ }
61
+ /** Get column width based on field type */
62
+ function getColumnWidth(field) {
63
+ if (isLongTextField(field))
64
+ return 300;
65
+ if (field.enum)
66
+ return 110;
67
+ if (field.type === 'boolean')
68
+ return 90;
69
+ if (field.type === 'number')
70
+ return 100;
71
+ if (field.type === 'date')
72
+ return 130;
73
+ if (field.type === 'string[]')
74
+ return 180;
75
+ if (field.type === 'number[]')
76
+ return 140;
77
+ if (field.type === 'json')
78
+ return 200;
79
+ return 160; // default string
80
+ }
81
+ /** Generate table columns from model fields — server-side filter & sort */
82
+ function generateColumns(fields, modelName, aiButtons) {
83
+ const cols = fields
84
+ .filter((f) => f.name !== 'id') // skip id column in form
85
+ .map((f) => {
86
+ const label = f.description || FALLBACK_LABELS[f.name] || f.name;
87
+ const width = getColumnWidth(f);
88
+ const extras = [` width: ${width},`];
89
+ const renders = [];
90
+ if (f.type === 'boolean') {
91
+ renders.push(` render: (val: boolean) => <Tag color={val ? 'green' : 'red'}>{val ? '是' : '否'}</Tag>,`);
92
+ }
93
+ else if (f.enum) {
94
+ // Enum columns: Tag render + server-side column filter
95
+ renders.push(` render: (val: string) => val ? <Tag color={tagColors?.['${f.name}']?.[val] || 'blue'}>{val}</Tag> : '-',`);
96
+ const filterItems = f.enum.map(v => ` { text: '${v}', value: '${v}' },`).join('\n');
97
+ extras.push(` filters: [\n${filterItems}\n ],`);
98
+ extras.push(` filteredValue: tableFilters.${f.name} || null,`);
99
+ }
100
+ else if (f.type === 'string[]') {
101
+ renders.push(` render: (val: string[]) => val?.map((v, i) => <Tag key={i}>{v}</Tag>),`);
102
+ }
103
+ else if (f.type === 'number[]') {
104
+ renders.push(` render: (val: number[]) => val?.join(', '),`);
105
+ }
106
+ else if (f.type === 'number') {
107
+ // Number columns: server-side sortable
108
+ extras.push(` sorter: true,`);
109
+ extras.push(` sortOrder: tableSorter.field === '${f.name}' ? tableSorter.order : null,`);
110
+ }
111
+ else if (f.type === 'date') {
112
+ // Date columns: server-side range filter
113
+ extras.push(` filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }: any) => (
114
+ <div style={{ padding: 8 }}>
115
+ <DatePicker.RangePicker
116
+ style={{ marginBottom: 8, display: 'block' }}
117
+ value={selectedKeys[0] ? selectedKeys : []}
118
+ onChange={(dates) => {
119
+ setSelectedKeys(dates ? [dates] : []);
120
+ confirm({ closeDropdown: false });
121
+ }}
122
+ />
123
+ <Space>
124
+ <Button type="primary" size="small" onClick={() => confirm()}>筛选</Button>
125
+ <Button size="small" onClick={() => { clearFilters?.(); confirm(); }}>重置</Button>
126
+ </Space>
127
+ </div>
128
+ ),`);
129
+ extras.push(` filteredValue: tableFilters.${f.name} || null,`);
130
+ }
131
+ else if (isLongTextField(f)) {
132
+ // Long text: auto wrap + 2-line ellipsis with expandable
133
+ extras.push(` onCell: () => ({ style: { wordBreak: 'break-word' as const } }),`);
134
+ renders.push(` render: (val: string) => val ? <Typography.Paragraph ellipsis={{ rows: 2, expandable: 'collapsible', symbol: '展开' }} style={{ marginBottom: 0 }}>{val}</Typography.Paragraph> : '-',`);
135
+ }
136
+ else if (f.type === 'string' && !f.enum) {
137
+ // Short string: tooltip ellipsis
138
+ extras.push(` ellipsis: true,`);
139
+ }
140
+ return ` {
141
+ title: '${label}',
142
+ dataIndex: '${f.name}',
143
+ key: '${f.name}',
144
+ ${extras.join('\n')}${renders.join('\n')} },`;
145
+ })
146
+ .join('\n');
147
+ // Add action column
148
+ const aiButtonMenuCode = aiButtons && aiButtons.length > 0
149
+ ? `<Tooltip title="AI 助手"><Dropdown menu={{ items: aiButtonMenuItems(record) }}>
150
+ <Button type="text" size="small" icon={<ThunderboltOutlined />} />
151
+ </Dropdown></Tooltip>`
152
+ : '';
153
+ const actionButtons = [
154
+ `<Tooltip title="编辑"><Button type="text" size="small" icon={<EditOutlined />} onClick={() => handleEdit(record)} /></Tooltip>`,
155
+ aiButtonMenuCode,
156
+ `<Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}>
157
+ <Tooltip title="删除"><Button type="text" size="small" danger icon={<DeleteOutlined />} /></Tooltip>
158
+ </Popconfirm>`,
159
+ ].filter(Boolean).join('\n ');
160
+ return `${cols}
161
+ {
162
+ title: '操作',
163
+ key: 'action',
164
+ width: ${aiButtons && aiButtons.length > 0 ? 120 : 90},
165
+ fixed: 'right' as const,
166
+ render: (_: unknown, record: ${toPascalCase(modelName)}Record) => (
167
+ <Space>
168
+ ${actionButtons}
169
+ </Space>
170
+ ),
171
+ },`;
172
+ }
173
+ /** Build display label from model description */
174
+ function buildLabel(description, pascalName) {
175
+ return description || pascalName;
176
+ }
177
+ /** Generate CRUD page template from model schema */
178
+ function crudPageTemplate(model, aiButtons) {
179
+ const pascalName = toPascalCase(model.name);
180
+ const recordType = `${pascalName}Record`;
181
+ // Detect field types for conditional logic
182
+ const dateFields = model.fields.filter(f => f.type === 'date').map(f => f.name);
183
+ const hasDateFields = dateFields.length > 0;
184
+ // Build TypeScript interface from fields
185
+ const fieldDefs = model.fields.map((f) => {
186
+ const tsType = f.type === 'string[]' ? 'string[]'
187
+ : f.type === 'number[]' ? 'number[]'
188
+ : f.type === 'json' ? 'Record<string, unknown>'
189
+ : f.type === 'number' ? 'number'
190
+ : f.type === 'boolean' ? 'boolean'
191
+ : f.type === 'date' ? 'string'
192
+ : 'string';
193
+ return ` ${f.name}${f.required ? '' : '?'}: ${tsType};`;
194
+ }).join('\n');
195
+ const columns = generateColumns(model.fields, model.name, aiButtons);
196
+ const formItems = model.fields
197
+ .filter((f) => f.name !== 'id') // id is auto-generated
198
+ .map((f) => fieldToFormItem(f, model.name))
199
+ .join('\n');
200
+ // Generate handleEdit with date conversion
201
+ const handleEditBody = hasDateFields
202
+ ? `const handleEdit = (record: ${recordType}) => {
203
+ setEditingRecord(record);
204
+ const formValues = { ...record };
205
+ ${dateFields.map(f => ` if (formValues.${f}) formValues.${f} = dayjs(formValues.${f}) as any;`).join('\n')}
206
+ form.setFieldsValue(formValues);
207
+ setModalOpen(true);
208
+ };`
209
+ : `const handleEdit = (record: ${recordType}) => {
210
+ setEditingRecord(record);
211
+ form.setFieldsValue(record);
212
+ setModalOpen(true);
213
+ };`;
214
+ // Generate handleSave with date serialization
215
+ const handleSaveBody = hasDateFields
216
+ ? `const handleSave = async () => {
217
+ try {
218
+ const values = await form.validateFields();
219
+ ${dateFields.map(f => ` if (values.${f}) values.${f} = values.${f}.format('YYYY-MM-DD');`).join('\n')}
220
+ if (editingRecord?.id) {
221
+ await update(editingRecord.id, values);
222
+ message.success('更新成功');
223
+ } else {
224
+ await create(values);
225
+ message.success('创建成功');
226
+ }
227
+ setModalOpen(false);
228
+ fetchData();
229
+ } catch {
230
+ // form validation failed
231
+ }
232
+ };`
233
+ : `const handleSave = async () => {
234
+ try {
235
+ const values = await form.validateFields();
236
+ if (editingRecord?.id) {
237
+ await update(editingRecord.id, values);
238
+ message.success('更新成功');
239
+ } else {
240
+ await create(values);
241
+ message.success('创建成功');
242
+ }
243
+ setModalOpen(false);
244
+ fetchData();
245
+ } catch {
246
+ // form validation failed
247
+ }
248
+ };`;
249
+ const dayjsImport = hasDateFields ? `\nimport dayjs from 'dayjs';` : '';
250
+ const hasAIButtons = aiButtons && aiButtons.length > 0;
251
+ // Build imports — merge AI-specific imports into existing lines
252
+ const antdExtra = hasAIButtons ? ', Dropdown' : '';
253
+ const iconsExtra = hasAIButtons ? ', ThunderboltOutlined' : '';
254
+ const extraIcons = ', EditOutlined, DeleteOutlined';
255
+ const loomExtra = hasAIButtons ? ', AIContext' : '';
256
+ const reactExtra = hasAIButtons ? ', useContext' : '';
257
+ return `import React, { useEffect, useState, useCallback${reactExtra} } from 'react';
258
+ import { Table, Button, Modal, Form, Input, InputNumber, Select, Switch, DatePicker, Space, Popconfirm, message, Tag, Card, Flex, Tooltip, Typography, type TableProps${antdExtra} } from 'antd';
259
+ import { PlusOutlined${iconsExtra}${extraIcons} } from '@ant-design/icons';
260
+ import { useData${loomExtra} } from '@loom-framework/frontend-antd';${dayjsImport}
261
+
262
+ interface ${recordType} {
263
+ id: string;
264
+ ${fieldDefs}
265
+ }
266
+
267
+ const modelFields: { name: string; type: string }[] = [
268
+ ${model.fields.map(f => ` { name: '${f.name}', type: '${f.type}' },`).join('\n')}
269
+ ];
270
+
271
+ export function ${pascalName}Page(): React.ReactElement {
272
+ const { list, create, update, remove, loading, refresh } = useData<${recordType}>('${model.name}');
273
+ const [form] = Form.useForm();
274
+ const [modalOpen, setModalOpen] = useState(false);
275
+ const [editingRecord, setEditingRecord] = useState<${recordType} | null>(null);
276
+ const [tableFilters, setTableFilters] = useState<Record<string, any>>({});
277
+ const [tableSorter, setTableSorter] = useState<{ field: string; order: 'ascend' | 'descend' | null }>({ field: '', order: null });
278
+
279
+ const fetchData = useCallback((filters?: Record<string, (string | number | boolean | null)[] | null>, sorter?: { field: string; order: 'ascend' | 'descend' | null }) => {
280
+ const currentFilters = filters ?? tableFilters;
281
+ const currentSorter = sorter ?? tableSorter;
282
+ const queryParams: any = {};
283
+ // Build filter from antd column filter values
284
+ const apiFilter: Record<string, unknown> = {};
285
+ for (const [key, val] of Object.entries(currentFilters)) {
286
+ if (val && val.length > 0) {
287
+ const field = modelFields.find(f => f.name === key);
288
+ if (field?.type === 'date') {
289
+ // Date range: val is [dayjs, dayjs] stored in filter
290
+ apiFilter[key] = { __range: val.map((v: any) => v?.format?.('YYYY-MM-DD') || v) };
291
+ } else if (val.length === 1) {
292
+ apiFilter[key] = val[0];
293
+ } else {
294
+ // Multiple filter values for a single column (e.g. subject in [数学, 英语])
295
+ apiFilter[key] = val;
296
+ }
297
+ }
298
+ }
299
+ if (Object.keys(apiFilter).length > 0) queryParams.filter = apiFilter;
300
+ // Build sort
301
+ if (currentSorter.field && currentSorter.order) {
302
+ queryParams.sort = currentSorter.field;
303
+ queryParams.sortOrder = currentSorter.order === 'descend' ? 'desc' : 'asc';
304
+ }
305
+ refresh(queryParams);
306
+ }, [refresh, tableFilters, tableSorter]);
307
+
308
+ useEffect(() => {
309
+ fetchData({}, { field: '', order: null });
310
+ }, []);
311
+
312
+ const handleAdd = () => {
313
+ setEditingRecord(null);
314
+ form.resetFields();
315
+ setModalOpen(true);
316
+ };
317
+
318
+ ${handleEditBody}
319
+
320
+ const handleDelete = async (id: string) => {
321
+ try {
322
+ await remove(id);
323
+ message.success('删除成功');
324
+ fetchData();
325
+ } catch {
326
+ message.error('删除失败');
327
+ }
328
+ };
329
+
330
+ ${handleSaveBody}
331
+ ${hasAIButtons ? `
332
+ const ai = useContext(AIContext);
333
+
334
+ // Build context object from the current record for AI prompts
335
+ // Key = raw field name (matches {{var}} in prompt templates)
336
+ // Value = description + value for fields with descriptions
337
+ const buildRecordContext = (record: ${recordType}): Record<string, string | string[] | number | boolean | null | undefined> => {
338
+ const labelMap: Record<string, string> = {
339
+ ${model.fields.map(f => ` ${f.name}: '${f.description || ''}',`).join('\n')}
340
+ };
341
+ const ctx: Record<string, string | string[] | number | boolean | null | undefined> = {};
342
+ for (const [k, v] of Object.entries(record)) {
343
+ if (v != null && v !== '' && !(Array.isArray(v) && v.length === 0)) {
344
+ ctx[k] = v as string | string[] | number | boolean | null | undefined;
345
+ }
346
+ }
347
+ return ctx;
348
+ };
349
+
350
+ const aiButtonMenuItems = (record: ${recordType}) => {
351
+ const ctx = buildRecordContext(record);
352
+ return [
353
+ ${aiButtons.map(btn => {
354
+ return ` { key: '${btn.id}', label: '${btn.label}', onClick: () => ai?.triggerAI({ buttonId: '${btn.id}', label: '${btn.label}', prompt: '${btn.prompt.replace(/'/g, "\\'").replace(/\n/g, "\\n")}', context: ctx }) },`;
355
+ }).join('\n')}
356
+ ];
357
+ };` : ''}
358
+
359
+ const columns: TableProps<${recordType}>['columns'] = [
360
+ ${columns}
361
+ ];
362
+ ${generateTagColors(model.fields)}
363
+ const handleTableChange: TableProps<${recordType}>['onChange'] = (pagination, filters, sorter) => {
364
+ const newFilters = filters as Record<string, any>;
365
+ const newSorter = !Array.isArray(sorter) && sorter.field
366
+ ? { field: sorter.field as string, order: sorter.order as 'ascend' | 'descend' | null }
367
+ : { field: '', order: null };
368
+ setTableFilters(newFilters);
369
+ setTableSorter(newSorter);
370
+ fetchData(newFilters, newSorter);
371
+ };
372
+
373
+ return (
374
+ <>
375
+ <Card>
376
+ <Flex justify="space-between" align="center" style={{ marginBottom: 16 }}>
377
+ <h2 style={{ margin: 0 }}>${buildLabel(model.description, pascalName)}</h2>
378
+ <Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
379
+ 新增
380
+ </Button>
381
+ </Flex>
382
+
383
+ <Table
384
+ columns={columns}
385
+ dataSource={list}
386
+ rowKey="id"
387
+ loading={loading}
388
+ size="middle"
389
+ scroll={{ x: 'max-content' }}
390
+ onChange={handleTableChange}
391
+ pagination={{ pageSize: 10, showSizeChanger: true, showTotal: (total) => \`共 \${total} 条\` }}
392
+ />
393
+ </Card>
394
+
395
+ <Modal
396
+ title={editingRecord ? '编辑${buildLabel(model.description, pascalName)}' : '新增${buildLabel(model.description, pascalName)}'}
397
+ open={modalOpen}
398
+ onOk={handleSave}
399
+ onCancel={() => setModalOpen(false)}
400
+ destroyOnHidden
401
+ width={640}
402
+ >
403
+ <Form form={form} layout="vertical">
404
+ ${formItems}
405
+ </Form>
406
+ </Modal>
407
+ </>
408
+ );
409
+ }
410
+
411
+ export default ${pascalName}Page;
412
+ `;
413
+ }
414
+ /** Minimal skeleton page template (no model) */
415
+ const SKELETON_TEMPLATE = (pascalName) => `import React from 'react';
416
+
417
+ export interface ${pascalName}Props {
418
+ // TODO: Define page props
419
+ }
420
+
421
+ export function ${pascalName}(props: ${pascalName}Props): React.ReactElement {
422
+ return (
423
+ <div className="${pascalName.toLowerCase()}-page">
424
+ <h1>${pascalName}</h1>
425
+ <p>TODO: Implement this page.</p>
426
+ </div>
427
+ );
428
+ }
429
+
430
+ export default ${pascalName};
431
+ `;
432
+ export function registerGeneratePageCommand(program) {
433
+ program
434
+ .command('page <name>')
435
+ .description('Create a new frontend page component with PascalCase naming')
436
+ .option('--model <model>', 'Data model name from loom.config.ts to generate CRUD page (auto-generates capabilities and wires App.tsx)')
437
+ .action(async (name, cmdOptions) => {
438
+ try {
439
+ const projectRoot = await resolveProjectRoot();
440
+ const pascalName = toPascalCase(name);
441
+ const pageDir = path.join(projectRoot, 'frontend', 'src', 'components', 'pages');
442
+ const pagePath = path.join(pageDir, `${pascalName}.tsx`);
443
+ // Check if page already exists
444
+ try {
445
+ await fs.access(pagePath);
446
+ console.error(chalk.red(`Page "${pascalName}" already exists at ${pagePath}`));
447
+ process.exit(1);
448
+ }
449
+ catch {
450
+ // File does not exist, proceed
451
+ }
452
+ let template;
453
+ let modelLabel = pascalName;
454
+ if (cmdOptions.model) {
455
+ // Load config and find model schema
456
+ const config = await loadConfig(projectRoot);
457
+ const modelSchema = getModelSchema(config, cmdOptions.model);
458
+ if (!modelSchema) {
459
+ console.error(chalk.red(`Model "${cmdOptions.model}" not found in loom.config.ts`));
460
+ console.error(chalk.dim(`Available models: ${config.data.models.map((m) => m.name).join(', ')}`));
461
+ process.exit(1);
462
+ }
463
+ modelLabel = buildLabel(modelSchema.description, pascalName);
464
+ // Step 1: Auto-generate capabilities (Skill for data access via CLI)
465
+ const capResult = await generateCapabilities(projectRoot, config);
466
+ console.log(chalk.green('Capabilities generated'), chalk.dim(`(${capResult.filesWritten.length} files)`));
467
+ // Step 2: Generate CRUD page — filter aiButtons by placement
468
+ const modelAiButtons = config.aiButtons?.filter(btn => {
469
+ // No placement = show on all pages (backward compatible)
470
+ if (!btn.placement)
471
+ return true;
472
+ // Comma-separated list of model names
473
+ const targets = btn.placement.split(',').map(s => s.trim());
474
+ return targets.includes(cmdOptions.model);
475
+ });
476
+ template = crudPageTemplate(modelSchema, modelAiButtons);
477
+ }
478
+ else {
479
+ template = SKELETON_TEMPLATE(pascalName);
480
+ }
481
+ await fs.mkdir(pageDir, { recursive: true });
482
+ await fs.writeFile(pagePath, template, 'utf-8');
483
+ console.log(chalk.green('Page created successfully!'));
484
+ console.log();
485
+ console.log(chalk.bold(' Page:'), pascalName);
486
+ console.log(chalk.bold(' Path:'), path.join('frontend', 'src', 'components', 'pages', `${pascalName}.tsx`));
487
+ if (cmdOptions.model) {
488
+ console.log(chalk.bold(' Model:'), cmdOptions.model);
489
+ }
490
+ // Step 3: Auto-wire App.tsx when using --model
491
+ if (cmdOptions.model) {
492
+ const wired = await wireAppTsxAutomatic(projectRoot, pascalName, cmdOptions.model, modelLabel);
493
+ if (wired) {
494
+ console.log(chalk.green(' App.tsx wired automatically'));
495
+ // Also wire SkillManagementPage on first page generation
496
+ const skillWired = await wireSkillManagementPage(projectRoot);
497
+ if (skillWired) {
498
+ console.log(chalk.green(' Skill management page wired'));
499
+ }
500
+ }
501
+ else {
502
+ console.log(chalk.yellow(' Could not auto-wire App.tsx — add the page import, navItem, and switch case manually'));
503
+ }
504
+ }
505
+ else {
506
+ console.log();
507
+ console.log(chalk.dim(' Use --model <name> to generate a CRUD page from a data model.'));
508
+ }
509
+ }
510
+ catch (err) {
511
+ const message = err instanceof Error ? err.message : String(err);
512
+ console.error(chalk.red('Failed to create page:'), message);
513
+ process.exit(1);
514
+ }
515
+ });
516
+ }
517
+ /**
518
+ * Auto-wire App.tsx: add import, navItem, and switch case for a new page.
519
+ * Returns true if successful, false if App.tsx structure is unexpected.
520
+ */
521
+ async function wireAppTsxAutomatic(projectRoot, pascalName, modelKey, modelLabel) {
522
+ const appPath = path.join(projectRoot, 'frontend', 'src', 'App.tsx');
523
+ let content;
524
+ try {
525
+ content = await fs.readFile(appPath, 'utf-8');
526
+ }
527
+ catch {
528
+ return false;
529
+ }
530
+ // Check if this page is already wired (avoid duplicates)
531
+ if (content.includes(`from './components/pages/${pascalName}'`) || content.includes(`<${pascalName}Page`)) {
532
+ return false;
533
+ }
534
+ // Also check if navItem with same key already exists
535
+ if (content.includes(`key: '${modelKey}'`)) {
536
+ return false;
537
+ }
538
+ let modified = content;
539
+ // 1. Add import after the last import line
540
+ const importLine = `import ${pascalName}Page from './components/pages/${pascalName}';`;
541
+ const lastImportEnd = modified.lastIndexOf('\n', modified.indexOf('\nexport'));
542
+ if (lastImportEnd === -1)
543
+ return false;
544
+ modified = modified.slice(0, lastImportEnd + 1) + importLine + '\n' + modified.slice(lastImportEnd + 1);
545
+ // 2. Add navItem (before the closing ] of navItems array)
546
+ const navItemLine = ` { key: '${modelKey}', label: '${modelLabel}' },`;
547
+ const navItemsEnd = modified.indexOf('// Add more nav items');
548
+ if (navItemsEnd !== -1) {
549
+ // Insert before the comment placeholder
550
+ const lineStart = modified.lastIndexOf('\n', navItemsEnd) + 1;
551
+ modified = modified.slice(0, lineStart) + navItemLine + '\n' + modified.slice(lineStart);
552
+ }
553
+ else {
554
+ // Fallback: find the closing ] of navItems array
555
+ const navArrayMatch = modified.match(/const navItems\s*=\s*\[/);
556
+ if (!navArrayMatch)
557
+ return false;
558
+ const arrayStart = navArrayMatch.index + navArrayMatch[0].length;
559
+ // Find the matching ]
560
+ let depth = 1;
561
+ let pos = arrayStart;
562
+ while (pos < modified.length && depth > 0) {
563
+ if (modified[pos] === '[')
564
+ depth++;
565
+ else if (modified[pos] === ']')
566
+ depth--;
567
+ pos++;
568
+ }
569
+ const closingBracket = pos - 1;
570
+ modified = modified.slice(0, closingBracket) + navItemLine + '\n' + modified.slice(closingBracket);
571
+ }
572
+ // 3. Add switch case — before skill-management case if present, otherwise before default
573
+ const caseLine = ` case '${modelKey}': return <${pascalName}Page />;`;
574
+ const skillCaseIdx = modified.indexOf("case 'skill-management':");
575
+ const insertAnchor = skillCaseIdx !== -1 ? skillCaseIdx : modified.indexOf('default:');
576
+ if (insertAnchor === -1)
577
+ return false;
578
+ const insertLineStart = modified.lastIndexOf('\n', insertAnchor) + 1;
579
+ modified = modified.slice(0, insertLineStart) + caseLine + '\n' + modified.slice(insertLineStart);
580
+ // 4. Ensure baseUrl="" on AppShell (prevent /api/v1/api/v1 double prefix)
581
+ if (modified.includes('<AppShell') && !modified.includes('baseUrl=')) {
582
+ modified = modified.replace('<AppShell', '<AppShell\n baseUrl=""');
583
+ }
584
+ await fs.writeFile(appPath, modified, 'utf-8');
585
+ return true;
586
+ }
587
+ /**
588
+ * Auto-wire the SkillManagementPage into App.tsx.
589
+ * Called once when the first CRUD page is generated.
590
+ * Returns true if successful, false if already wired or structure is unexpected.
591
+ */
592
+ async function wireSkillManagementPage(projectRoot) {
593
+ const appPath = path.join(projectRoot, 'frontend', 'src', 'App.tsx');
594
+ let content;
595
+ try {
596
+ content = await fs.readFile(appPath, 'utf-8');
597
+ }
598
+ catch {
599
+ return false;
600
+ }
601
+ // Check if already wired (avoid duplicates)
602
+ if (content.includes('SkillManagementPage')) {
603
+ return false;
604
+ }
605
+ let modified = content;
606
+ // 1. Add import after the last import line
607
+ const importLine = `import { SkillManagementPage } from '@loom-framework/frontend-antd';`;
608
+ const lastImportEnd = modified.lastIndexOf('\n', modified.indexOf('\nexport'));
609
+ if (lastImportEnd === -1)
610
+ return false;
611
+ modified = modified.slice(0, lastImportEnd + 1) + importLine + '\n' + modified.slice(lastImportEnd + 1);
612
+ // 2. Add navItem — always at the end of the array so it stays below all model pages
613
+ const navItemLine = ` { key: 'skill-management', label: 'Skill 管理' },`;
614
+ const navArrayMatch = modified.match(/const navItems\s*=\s*\[/);
615
+ if (!navArrayMatch)
616
+ return false;
617
+ const arrayStart = navArrayMatch.index + navArrayMatch[0].length;
618
+ let depth = 1;
619
+ let pos = arrayStart;
620
+ while (pos < modified.length && depth > 0) {
621
+ if (modified[pos] === '[')
622
+ depth++;
623
+ else if (modified[pos] === ']')
624
+ depth--;
625
+ pos++;
626
+ }
627
+ const closingBracket = pos - 1;
628
+ // Insert before the line containing the closing bracket
629
+ const lineStart = modified.lastIndexOf('\n', closingBracket) + 1;
630
+ modified = modified.slice(0, lineStart) + navItemLine + '\n' + modified.slice(lineStart);
631
+ // 3. Add switch case before default
632
+ const caseLine = ` case 'skill-management': return <SkillManagementPage />;`;
633
+ const defaultCase = modified.indexOf('default:');
634
+ if (defaultCase === -1)
635
+ return false;
636
+ const defaultLineStart = modified.lastIndexOf('\n', defaultCase) + 1;
637
+ modified = modified.slice(0, defaultLineStart) + caseLine + '\n' + modified.slice(defaultLineStart);
638
+ await fs.writeFile(appPath, modified, 'utf-8');
639
+ return true;
640
+ }
641
+ //# sourceMappingURL=generate-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-page.js","sourceRoot":"","sources":["../../../src/cli/commands/generate-page.ts"],"names":[],"mappings":"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"}