@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.
Files changed (77) hide show
  1. package/dist/adapters/base.d.ts +31 -0
  2. package/dist/adapters/base.d.ts.map +1 -0
  3. package/dist/adapters/base.js +69 -0
  4. package/dist/adapters/base.js.map +1 -0
  5. package/dist/adapters/factory.d.ts +8 -0
  6. package/dist/adapters/factory.d.ts.map +1 -0
  7. package/dist/adapters/factory.js +25 -0
  8. package/dist/adapters/factory.js.map +1 -0
  9. package/dist/adapters/filesystem.d.ts +46 -0
  10. package/dist/adapters/filesystem.d.ts.map +1 -0
  11. package/dist/adapters/filesystem.js +321 -0
  12. package/dist/adapters/filesystem.js.map +1 -0
  13. package/dist/adapters/index.d.ts +10 -0
  14. package/dist/adapters/index.d.ts.map +1 -0
  15. package/dist/adapters/index.js +8 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/sqlite.d.ts +37 -0
  18. package/dist/adapters/sqlite.d.ts.map +1 -0
  19. package/dist/adapters/sqlite.js +264 -0
  20. package/dist/adapters/sqlite.js.map +1 -0
  21. package/dist/backend/index.js +1 -1
  22. package/dist/backend/index.js.map +1 -1
  23. package/dist/backend/routes/skills.d.ts +3 -3
  24. package/dist/backend/routes/skills.d.ts.map +1 -1
  25. package/dist/backend/routes/skills.js +3 -3
  26. package/dist/backend/routes/skills.js.map +1 -1
  27. package/dist/backend/services/skill-archive.d.ts +13 -0
  28. package/dist/backend/services/skill-archive.d.ts.map +1 -0
  29. package/dist/backend/services/skill-archive.js +84 -0
  30. package/dist/backend/services/skill-archive.js.map +1 -0
  31. package/dist/backend/services/skill-parser.d.ts +41 -0
  32. package/dist/backend/services/skill-parser.d.ts.map +1 -0
  33. package/dist/backend/services/skill-parser.js +184 -0
  34. package/dist/backend/services/skill-parser.js.map +1 -0
  35. package/dist/backend/services/skill-service.d.ts +113 -0
  36. package/dist/backend/services/skill-service.d.ts.map +1 -0
  37. package/dist/backend/services/skill-service.js +265 -0
  38. package/dist/backend/services/skill-service.js.map +1 -0
  39. package/dist/cli/commands/data.js +2 -2
  40. package/dist/cli/commands/data.js.map +1 -1
  41. package/dist/cli/commands/generate-dashboard.d.ts.map +1 -1
  42. package/dist/cli/commands/generate-dashboard.js +1 -450
  43. package/dist/cli/commands/generate-dashboard.js.map +1 -1
  44. package/dist/cli/commands/generate-page.d.ts.map +1 -1
  45. package/dist/cli/commands/generate-page.js +4 -436
  46. package/dist/cli/commands/generate-page.js.map +1 -1
  47. package/dist/cli/commands/serve.d.ts +12 -0
  48. package/dist/cli/commands/serve.d.ts.map +1 -0
  49. package/dist/cli/commands/serve.js +43 -0
  50. package/dist/cli/commands/serve.js.map +1 -0
  51. package/dist/cli/framework.d.ts +28 -0
  52. package/dist/cli/framework.d.ts.map +1 -0
  53. package/dist/cli/framework.js +29 -0
  54. package/dist/cli/framework.js.map +1 -0
  55. package/dist/cli/helpers/i18n-template.d.ts +13 -0
  56. package/dist/cli/helpers/i18n-template.d.ts.map +1 -0
  57. package/dist/cli/helpers/i18n-template.js +48 -0
  58. package/dist/cli/helpers/i18n-template.js.map +1 -0
  59. package/dist/cli/templates/crud-page.d.ts +14 -0
  60. package/dist/cli/templates/crud-page.d.ts.map +1 -0
  61. package/dist/cli/templates/crud-page.js +405 -0
  62. package/dist/cli/templates/crud-page.js.map +1 -0
  63. package/dist/cli/templates/dashboard-page.d.ts +11 -0
  64. package/dist/cli/templates/dashboard-page.d.ts.map +1 -0
  65. package/dist/cli/templates/dashboard-page.js +456 -0
  66. package/dist/cli/templates/dashboard-page.js.map +1 -0
  67. package/dist/cli/templates/index.d.ts +2 -0
  68. package/dist/cli/templates/index.d.ts.map +1 -1
  69. package/dist/cli/templates/index.js +2 -0
  70. package/dist/cli/templates/index.js.map +1 -1
  71. package/dist/config.d.ts +22 -22
  72. package/dist/dashboard-config.d.ts +10 -10
  73. package/dist/index.d.ts +7 -7
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +5 -5
  76. package/dist/index.js.map +1 -1
  77. 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 { fieldToFormItem } from '../helpers/field-template.js';
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
- /** Generate i18n key prefix for a model */
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 = SKELETON_TEMPLATE(pascalName);
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"}