@loom-framework/core 0.1.0-alpha.39 → 0.1.0-alpha.40
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/backend/ai/button-resolver.d.ts +17 -0
- package/dist/backend/ai/button-resolver.d.ts.map +1 -0
- package/dist/backend/ai/button-resolver.js +40 -0
- package/dist/backend/ai/button-resolver.js.map +1 -0
- package/dist/backend/ai/engine.d.ts +51 -0
- package/dist/backend/ai/engine.d.ts.map +1 -0
- package/dist/backend/ai/engine.js +188 -0
- package/dist/backend/ai/engine.js.map +1 -0
- package/dist/backend/ai/index.d.ts +11 -0
- package/dist/backend/ai/index.d.ts.map +1 -0
- package/dist/backend/ai/index.js +8 -0
- package/dist/backend/ai/index.js.map +1 -0
- package/dist/backend/ai/output-parser.d.ts +29 -0
- package/dist/backend/ai/output-parser.d.ts.map +1 -0
- package/dist/backend/ai/output-parser.js +247 -0
- package/dist/backend/ai/output-parser.js.map +1 -0
- package/dist/backend/ai/session-manager.d.ts +102 -0
- package/dist/backend/ai/session-manager.d.ts.map +1 -0
- package/dist/backend/ai/session-manager.js +291 -0
- package/dist/backend/ai/session-manager.js.map +1 -0
- package/dist/backend/index.d.ts +61 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +160 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/observe/index.d.ts +6 -0
- package/dist/backend/observe/index.d.ts.map +1 -0
- package/dist/backend/observe/index.js +5 -0
- package/dist/backend/observe/index.js.map +1 -0
- package/dist/backend/observe/logger.d.ts +28 -0
- package/dist/backend/observe/logger.d.ts.map +1 -0
- package/dist/backend/observe/logger.js +80 -0
- package/dist/backend/observe/logger.js.map +1 -0
- package/dist/backend/observe/types.d.ts +26 -0
- package/dist/backend/observe/types.d.ts.map +1 -0
- package/dist/backend/observe/types.js +7 -0
- package/dist/backend/observe/types.js.map +1 -0
- package/dist/backend/routes/chat.d.ts +31 -0
- package/dist/backend/routes/chat.d.ts.map +1 -0
- package/dist/backend/routes/chat.js +426 -0
- package/dist/backend/routes/chat.js.map +1 -0
- package/dist/backend/routes/data.d.ts +13 -0
- package/dist/backend/routes/data.d.ts.map +1 -0
- package/dist/backend/routes/data.js +129 -0
- package/dist/backend/routes/data.js.map +1 -0
- package/dist/backend/routes/health.d.ts +7 -0
- package/dist/backend/routes/health.d.ts.map +1 -0
- package/dist/backend/routes/health.js +15 -0
- package/dist/backend/routes/health.js.map +1 -0
- package/dist/backend/routes/index.d.ts +9 -0
- package/dist/backend/routes/index.d.ts.map +1 -0
- package/dist/backend/routes/index.js +8 -0
- package/dist/backend/routes/index.js.map +1 -0
- package/dist/backend/routes/upload.d.ts +24 -0
- package/dist/backend/routes/upload.d.ts.map +1 -0
- package/dist/backend/routes/upload.js +67 -0
- package/dist/backend/routes/upload.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +170 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/data.d.ts +11 -0
- package/dist/cli/commands/data.d.ts.map +1 -0
- package/dist/cli/commands/data.js +137 -0
- package/dist/cli/commands/data.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +114 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-capabilities.d.ts +8 -0
- package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
- package/dist/cli/commands/generate-capabilities.js +40 -0
- package/dist/cli/commands/generate-capabilities.js.map +1 -0
- package/dist/cli/commands/generate-cli-command.d.ts +8 -0
- package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
- package/dist/cli/commands/generate-cli-command.js +64 -0
- package/dist/cli/commands/generate-cli-command.js.map +1 -0
- package/dist/cli/commands/generate-page.d.ts +9 -0
- package/dist/cli/commands/generate-page.d.ts.map +1 -0
- package/dist/cli/commands/generate-page.js +325 -0
- package/dist/cli/commands/generate-page.js.map +1 -0
- package/dist/cli/commands/generate-skill.d.ts +8 -0
- package/dist/cli/commands/generate-skill.d.ts.map +1 -0
- package/dist/cli/commands/generate-skill.js +75 -0
- package/dist/cli/commands/generate-skill.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +6 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +17 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +400 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +9 -0
- package/dist/cli/commands/observe.d.ts.map +1 -0
- package/dist/cli/commands/observe.js +142 -0
- package/dist/cli/commands/observe.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +9 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +186 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/helpers/duration.d.ts +5 -0
- package/dist/cli/helpers/duration.d.ts.map +1 -0
- package/dist/cli/helpers/duration.js +19 -0
- package/dist/cli/helpers/duration.js.map +1 -0
- package/dist/cli/helpers/field-template.d.ts +9 -0
- package/dist/cli/helpers/field-template.d.ts.map +1 -0
- package/dist/cli/helpers/field-template.js +59 -0
- package/dist/cli/helpers/field-template.js.map +1 -0
- package/dist/cli/helpers/naming.d.ts +6 -0
- package/dist/cli/helpers/naming.d.ts.map +1 -0
- package/dist/cli/helpers/naming.js +14 -0
- package/dist/cli/helpers/naming.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +10 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +31 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/server-bin.d.ts +12 -0
- package/dist/server-bin.d.ts.map +1 -0
- package/dist/server-bin.js +75 -0
- package/dist/server-bin.js.map +1 -0
- package/package.json +17 -5
- package/templates/skill/SKILL.md +91 -0
- package/templates/skill/references/README.md +67 -0
- package/templates/skill/references/data-model.md +87 -0
- package/templates/skill/references/skill-development.md +46 -0
- package/templates/skill/references/troubleshooting.md +35 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loom skill - Skill management commands
|
|
3
|
+
*
|
|
4
|
+
* loom skill list - Scan .claude/skills/ directory, list all skills
|
|
5
|
+
* loom skill validate [name] - Validate SKILL.md frontmatter and references
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { promises as fs } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { resolveProjectRoot } from '../utils.js';
|
|
11
|
+
export function registerSkillCommand(program) {
|
|
12
|
+
const skill = program
|
|
13
|
+
.command('skill')
|
|
14
|
+
.description('Skill management commands');
|
|
15
|
+
// loom skill list
|
|
16
|
+
skill
|
|
17
|
+
.command('list')
|
|
18
|
+
.description('List all skills in the project')
|
|
19
|
+
.action(async () => {
|
|
20
|
+
try {
|
|
21
|
+
const projectRoot = await resolveProjectRoot();
|
|
22
|
+
const skillsDir = path.join(projectRoot, '.claude', 'skills');
|
|
23
|
+
let entries;
|
|
24
|
+
try {
|
|
25
|
+
entries = await fs.readdir(skillsDir);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
console.log(chalk.yellow('No skills directory found.'));
|
|
29
|
+
console.log(chalk.dim(' Run `loom generate skill <name>` to create one.'));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const skillDirs = entries.filter(async (entry) => {
|
|
33
|
+
const stat = await fs.stat(path.join(skillsDir, entry));
|
|
34
|
+
return stat.isDirectory();
|
|
35
|
+
});
|
|
36
|
+
const validSkillDirs = [];
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
const entryPath = path.join(skillsDir, entry);
|
|
39
|
+
try {
|
|
40
|
+
const stat = await fs.stat(entryPath);
|
|
41
|
+
if (stat.isDirectory()) {
|
|
42
|
+
validSkillDirs.push(entry);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (validSkillDirs.length === 0) {
|
|
50
|
+
console.log(chalk.yellow('No skills found.'));
|
|
51
|
+
console.log(chalk.dim(' Run `loom generate skill <name>` to create one.'));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
console.log(chalk.bold(`Skills (${validSkillDirs.length}):`));
|
|
55
|
+
console.log();
|
|
56
|
+
for (const dirName of validSkillDirs) {
|
|
57
|
+
const skillMdPath = path.join(skillsDir, dirName, 'SKILL.md');
|
|
58
|
+
let hasSkillMd = false;
|
|
59
|
+
try {
|
|
60
|
+
await fs.access(skillMdPath);
|
|
61
|
+
hasSkillMd = true;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// No SKILL.md
|
|
65
|
+
}
|
|
66
|
+
const marker = hasSkillMd ? chalk.green('✓') : chalk.red('✗');
|
|
67
|
+
console.log(` ${marker} ${chalk.cyan(dirName)}`);
|
|
68
|
+
if (!hasSkillMd) {
|
|
69
|
+
console.log(chalk.dim(` Missing SKILL.md`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
75
|
+
console.error(chalk.red('Failed to list skills:'), message);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// loom skill validate [name]
|
|
80
|
+
skill
|
|
81
|
+
.command('validate [name]')
|
|
82
|
+
.description('Validate skill SKILL.md frontmatter and references')
|
|
83
|
+
.action(async (name) => {
|
|
84
|
+
try {
|
|
85
|
+
const projectRoot = await resolveProjectRoot();
|
|
86
|
+
const skillsDir = path.join(projectRoot, '.claude', 'skills');
|
|
87
|
+
if (name) {
|
|
88
|
+
// Validate specific skill
|
|
89
|
+
await validateSkill(skillsDir, name);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Validate all skills
|
|
93
|
+
let entries;
|
|
94
|
+
try {
|
|
95
|
+
entries = await fs.readdir(skillsDir);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
console.log(chalk.yellow('No skills directory found.'));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const dirs = [];
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
try {
|
|
104
|
+
const stat = await fs.stat(path.join(skillsDir, entry));
|
|
105
|
+
if (stat.isDirectory())
|
|
106
|
+
dirs.push(entry);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (dirs.length === 0) {
|
|
113
|
+
console.log(chalk.yellow('No skills to validate.'));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
let allValid = true;
|
|
117
|
+
for (const dir of dirs) {
|
|
118
|
+
const valid = await validateSkill(skillsDir, dir);
|
|
119
|
+
if (!valid)
|
|
120
|
+
allValid = false;
|
|
121
|
+
}
|
|
122
|
+
if (!allValid) {
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
129
|
+
console.error(chalk.red('Validation failed:'), message);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Validate a single skill directory
|
|
136
|
+
*/
|
|
137
|
+
async function validateSkill(skillsDir, name) {
|
|
138
|
+
const skillDir = path.join(skillsDir, name);
|
|
139
|
+
const errors = [];
|
|
140
|
+
// Check SKILL.md exists
|
|
141
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
142
|
+
try {
|
|
143
|
+
const content = await fs.readFile(skillMdPath, 'utf-8');
|
|
144
|
+
// Check frontmatter exists
|
|
145
|
+
if (!content.startsWith('---')) {
|
|
146
|
+
errors.push('SKILL.md is missing frontmatter (must start with ---)');
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const frontmatterEnd = content.indexOf('---', 3);
|
|
150
|
+
if (frontmatterEnd === -1) {
|
|
151
|
+
errors.push('SKILL.md has unclosed frontmatter');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const frontmatter = content.slice(3, frontmatterEnd).trim();
|
|
155
|
+
// Check for required frontmatter fields
|
|
156
|
+
if (!frontmatter.includes('name:')) {
|
|
157
|
+
errors.push('SKILL.md frontmatter missing "name" field');
|
|
158
|
+
}
|
|
159
|
+
if (!frontmatter.includes('version:')) {
|
|
160
|
+
errors.push('SKILL.md frontmatter missing "version" field');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
errors.push('SKILL.md not found');
|
|
167
|
+
}
|
|
168
|
+
// Check references/ directory exists
|
|
169
|
+
const referencesDir = path.join(skillDir, 'references');
|
|
170
|
+
try {
|
|
171
|
+
await fs.access(referencesDir);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
errors.push('references/ directory not found');
|
|
175
|
+
}
|
|
176
|
+
if (errors.length > 0) {
|
|
177
|
+
console.log(chalk.red(` ✗ ${name}`));
|
|
178
|
+
for (const error of errors) {
|
|
179
|
+
console.log(chalk.dim(` - ${error}`));
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
console.log(chalk.green(` ✓ ${name}`));
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../../src/cli/commands/skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../../src/cli/helpers/duration.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CActD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duration parsing utility - extracted for testability
|
|
3
|
+
*/
|
|
4
|
+
export function parseDuration(duration) {
|
|
5
|
+
const match = duration.match(/^(\d+)(s|m|h|d)$/);
|
|
6
|
+
if (!match) {
|
|
7
|
+
throw new Error(`Invalid duration: ${duration}. Use format like '1h', '30m', '7d'`);
|
|
8
|
+
}
|
|
9
|
+
const value = parseInt(match[1], 10);
|
|
10
|
+
const unit = match[2];
|
|
11
|
+
switch (unit) {
|
|
12
|
+
case 's': return value * 1000;
|
|
13
|
+
case 'm': return value * 60 * 1000;
|
|
14
|
+
case 'h': return value * 60 * 60 * 1000;
|
|
15
|
+
case 'd': return value * 24 * 60 * 60 * 1000;
|
|
16
|
+
default: throw new Error(`Unknown unit: ${unit}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=duration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.js","sourceRoot":"","sources":["../../../src/cli/helpers/duration.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,qCAAqC,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;QAC9B,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC;QACnC,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACxC,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC7C,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field-to-template utilities - extracted for testability
|
|
3
|
+
*/
|
|
4
|
+
import type { FieldDefinition, FieldType } from '../../index.js';
|
|
5
|
+
/** Map FieldType to Ant Design table column render hint */
|
|
6
|
+
export declare function fieldToColumnType(type: FieldType): string;
|
|
7
|
+
/** Generate Ant Design form item for a field */
|
|
8
|
+
export declare function fieldToFormItem(field: FieldDefinition, modelName: string): string;
|
|
9
|
+
//# sourceMappingURL=field-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-template.d.ts","sourceRoot":"","sources":["../../../src/cli/helpers/field-template.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjE,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAYzD;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAyCjF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field-to-template utilities - extracted for testability
|
|
3
|
+
*/
|
|
4
|
+
/** Map FieldType to Ant Design table column render hint */
|
|
5
|
+
export function fieldToColumnType(type) {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case 'number':
|
|
8
|
+
case 'number[]':
|
|
9
|
+
return "'right'";
|
|
10
|
+
case 'boolean':
|
|
11
|
+
return "'bool'";
|
|
12
|
+
case 'date':
|
|
13
|
+
return "'date'";
|
|
14
|
+
default:
|
|
15
|
+
return "'text'";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Generate Ant Design form item for a field */
|
|
19
|
+
export function fieldToFormItem(field, modelName) {
|
|
20
|
+
const name = field.name;
|
|
21
|
+
const label = field.description || name;
|
|
22
|
+
const requiredRule = field.required ? ` rules={[{ required: true, message: '请输入${label}' }]}` : '';
|
|
23
|
+
if (field.enum) {
|
|
24
|
+
const options = field.enum.map((v) => ` <Select.Option value="${v}">${v}</Select.Option>`).join('\n');
|
|
25
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
26
|
+
<Select placeholder="请选择${label}">
|
|
27
|
+
${options}
|
|
28
|
+
</Select>
|
|
29
|
+
</Form.Item>`;
|
|
30
|
+
}
|
|
31
|
+
switch (field.type) {
|
|
32
|
+
case 'boolean':
|
|
33
|
+
return ` <Form.Item name="${name}" label="${label}" valuePropName="checked">
|
|
34
|
+
<Switch />
|
|
35
|
+
</Form.Item>`;
|
|
36
|
+
case 'number':
|
|
37
|
+
case 'number[]':
|
|
38
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
39
|
+
<InputNumber style={{ width: '100%' }} />
|
|
40
|
+
</Form.Item>`;
|
|
41
|
+
case 'string[]':
|
|
42
|
+
return ` <Form.Item name="${name}" label="${label}">
|
|
43
|
+
<Select mode="tags" placeholder="请输入${label}" />
|
|
44
|
+
</Form.Item>`;
|
|
45
|
+
case 'json':
|
|
46
|
+
return ` <Form.Item name="${name}" label="${label}">
|
|
47
|
+
<Input.TextArea rows={4} placeholder="请输入JSON" />
|
|
48
|
+
</Form.Item>`;
|
|
49
|
+
case 'date':
|
|
50
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
51
|
+
<DatePicker style={{ width: '100%' }} />
|
|
52
|
+
</Form.Item>`;
|
|
53
|
+
default:
|
|
54
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
55
|
+
<Input placeholder="请输入${label}" />
|
|
56
|
+
</Form.Item>`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=field-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-template.js","sourceRoot":"","sources":["../../../src/cli/helpers/field-template.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,2DAA2D;AAC3D,MAAM,UAAU,iBAAiB,CAAC,IAAe;IAC/C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,UAAU;YACb,OAAO,SAAS,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC;QAClB;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,eAAe,CAAC,KAAsB,EAAE,SAAiB;IACvE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;IACxC,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,2CAA2C,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iCAAiC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7G,OAAO,0BAA0B,IAAI,YAAY,KAAK,IAAI,YAAY;kCACxC,KAAK;EACrC,OAAO;;mBAEU,CAAC;IAClB,CAAC;IAED,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,0BAA0B,IAAI,YAAY,KAAK;;mBAEzC,CAAC;QAChB,KAAK,QAAQ,CAAC;QACd,KAAK,UAAU;YACb,OAAO,0BAA0B,IAAI,YAAY,KAAK,IAAI,YAAY;;mBAEzD,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,0BAA0B,IAAI,YAAY,KAAK;8CACd,KAAK;mBAChC,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,0BAA0B,IAAI,YAAY,KAAK;;mBAEzC,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,0BAA0B,IAAI,YAAY,KAAK,IAAI,YAAY;;mBAEzD,CAAC;QAChB;YACE,OAAO,0BAA0B,IAAI,YAAY,KAAK,IAAI,YAAY;iCAC3C,KAAK;mBACnB,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../src/cli/helpers/naming.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Naming utilities - extracted for testability
|
|
3
|
+
*/
|
|
4
|
+
export function toPascalCase(name) {
|
|
5
|
+
return name
|
|
6
|
+
.split(/[-_]/)
|
|
7
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
8
|
+
.join('');
|
|
9
|
+
}
|
|
10
|
+
export function toCamelCase(name) {
|
|
11
|
+
const pascal = toPascalCase(name);
|
|
12
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../src/cli/helpers/naming.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SACzE,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom CLI - Main Program
|
|
3
|
+
*
|
|
4
|
+
* Registers all subcommands and runs the CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
export declare function createProgram(): Command;
|
|
8
|
+
export declare function run(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,aAAa,IAAI,OAAO,CAiBvC;AAED,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAGzC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom CLI - Main Program
|
|
3
|
+
*
|
|
4
|
+
* Registers all subcommands and runs the CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { registerGenerateCommand } from './commands/generate.js';
|
|
8
|
+
import { registerDevCommand } from './commands/dev.js';
|
|
9
|
+
import { registerBuildCommand } from './commands/build.js';
|
|
10
|
+
import { registerDataCommand } from './commands/data.js';
|
|
11
|
+
import { registerSkillCommand } from './commands/skill.js';
|
|
12
|
+
import { registerObserveCommand } from './commands/observe.js';
|
|
13
|
+
import { registerInitCommand } from './commands/init.js';
|
|
14
|
+
export function createProgram() {
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name('loom')
|
|
18
|
+
.description('Loom - Weave AI capabilities into your application')
|
|
19
|
+
.version('0.1.0');
|
|
20
|
+
registerInitCommand(program);
|
|
21
|
+
registerGenerateCommand(program);
|
|
22
|
+
registerDevCommand(program);
|
|
23
|
+
registerBuildCommand(program);
|
|
24
|
+
registerDataCommand(program);
|
|
25
|
+
registerSkillCommand(program);
|
|
26
|
+
registerObserveCommand(program);
|
|
27
|
+
return program;
|
|
28
|
+
}
|
|
29
|
+
export async function run() {
|
|
30
|
+
const program = createProgram();
|
|
31
|
+
await program.parseAsync(process.argv);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,oDAAoD,CAAC;SACjE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the project root directory.
|
|
6
|
+
* Walks up from CWD looking for loom.config.ts or loom.config.js.
|
|
7
|
+
* Falls back to CWD if no config found.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveProjectRoot(): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAoB1D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the project root directory.
|
|
8
|
+
* Walks up from CWD looking for loom.config.ts or loom.config.js.
|
|
9
|
+
* Falls back to CWD if no config found.
|
|
10
|
+
*/
|
|
11
|
+
export async function resolveProjectRoot() {
|
|
12
|
+
let current = process.cwd();
|
|
13
|
+
for (let i = 0; i < 20; i++) {
|
|
14
|
+
for (const candidate of ['loom.config.ts', 'loom.config.js']) {
|
|
15
|
+
try {
|
|
16
|
+
await fs.access(path.join(current, candidate));
|
|
17
|
+
return current;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const parent = path.dirname(current);
|
|
24
|
+
if (parent === current)
|
|
25
|
+
break; // reached root
|
|
26
|
+
current = parent;
|
|
27
|
+
}
|
|
28
|
+
// Fallback to CWD
|
|
29
|
+
return process.cwd();
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,KAAK,MAAM,SAAS,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;gBAC/C,OAAO,OAAO,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM,CAAC,eAAe;QAC9C,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,kBAAkB;IAClB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,7 @@ export type { SQLiteAdapterOptions } from './adapter-sqlite.js';
|
|
|
12
12
|
export { generateCapabilities } from './capability-generator.js';
|
|
13
13
|
export type { GenerateResult } from './capability-generator.js';
|
|
14
14
|
export { defineCommand } from './commands.js';
|
|
15
|
+
export { LoomServer, startServer } from './backend/index.js';
|
|
16
|
+
export type { LoomServerOptions } from './backend/index.js';
|
|
17
|
+
export { createProgram, run } from './cli/index.js';
|
|
15
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,aAAa,EACb,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACX,SAAS,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGrI,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,aAAa,EACb,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACX,SAAS,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGrI,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,4 +12,8 @@ export { SQLiteAdapter } from './adapter-sqlite.js';
|
|
|
12
12
|
export { generateCapabilities } from './capability-generator.js';
|
|
13
13
|
// Command Framework
|
|
14
14
|
export { defineCommand } from './commands.js';
|
|
15
|
+
// Backend
|
|
16
|
+
export { LoomServer, startServer } from './backend/index.js';
|
|
17
|
+
// CLI
|
|
18
|
+
export { createProgram, run } from './cli/index.js';
|
|
15
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkCH,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErI,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,uBAAuB;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGjE,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkCH,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErI,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,uBAAuB;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGjE,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG7D,MAAM;AACN,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -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=server-bin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-bin.d.ts","sourceRoot":"","sources":["../src/server-bin.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
const args = process.argv.slice(2);
|
|
12
|
+
let projectRoot = process.cwd();
|
|
13
|
+
let port;
|
|
14
|
+
let host;
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
const arg = args[i];
|
|
17
|
+
switch (arg) {
|
|
18
|
+
case '--port':
|
|
19
|
+
case '-p':
|
|
20
|
+
port = parseInt(args[++i], 10);
|
|
21
|
+
break;
|
|
22
|
+
case '--host':
|
|
23
|
+
case '-h':
|
|
24
|
+
host = args[++i];
|
|
25
|
+
break;
|
|
26
|
+
case '--help':
|
|
27
|
+
console.log(`
|
|
28
|
+
loom-server - Start a Loom backend server
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
loom-server [project-root] [options]
|
|
32
|
+
|
|
33
|
+
Options:
|
|
34
|
+
--port, -p <number> Server port (default: 3000)
|
|
35
|
+
--host, -h <string> Server host (default: 0.0.0.0)
|
|
36
|
+
--help Show this help message
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
loom-server
|
|
40
|
+
loom-server ./my-project
|
|
41
|
+
loom-server --port 8080 --host 127.0.0.1
|
|
42
|
+
`);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
default:
|
|
45
|
+
// Treat as project root path
|
|
46
|
+
if (!arg.startsWith('-')) {
|
|
47
|
+
projectRoot = arg;
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const serverConfig = {};
|
|
53
|
+
if (port !== undefined)
|
|
54
|
+
serverConfig.port = port;
|
|
55
|
+
if (host !== undefined)
|
|
56
|
+
serverConfig.host = host;
|
|
57
|
+
try {
|
|
58
|
+
const { LoomServer } = await import('./backend/index.js');
|
|
59
|
+
const server = new LoomServer({
|
|
60
|
+
projectRoot,
|
|
61
|
+
serverConfig,
|
|
62
|
+
});
|
|
63
|
+
await server.initialize();
|
|
64
|
+
await server.start();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof Error && error.message.includes('No loom.config.ts found')) {
|
|
68
|
+
console.error(`Error: No loom.config.ts found in ${projectRoot}`);
|
|
69
|
+
console.error('Create one with: loom init <name>');
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=server-bin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-bin.js","sourceRoot":"","sources":["../src/server-bin.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAChC,IAAI,IAAwB,CAAC;AAC7B,IAAI,IAAwB,CAAC;AAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACjB,MAAM;QACR,KAAK,QAAQ;YACX,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;CAejB,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB;YACE,6BAA6B;YAC7B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,WAAW,GAAG,GAAG,CAAC;YACpB,CAAC;YACD,MAAM;IACV,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAA4B,EAAE,CAAC;AACjD,IAAI,IAAI,KAAK,SAAS;IAAE,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC;AACjD,IAAI,IAAI,KAAK,SAAS;IAAE,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC;AAEjD,IAAI,CAAC;IACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,WAAW;QACX,YAAY;KACb,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC1B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,KAAK,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loom-framework/core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
4
|
-
"description": "Loom framework
|
|
3
|
+
"version": "0.1.0-alpha.40",
|
|
4
|
+
"description": "Loom framework - DataAdapter, Capability Generator, config system, backend server, CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"loom": "./dist/bin.js",
|
|
16
|
+
"loom-server": "./dist/server-bin.js"
|
|
17
|
+
},
|
|
14
18
|
"files": [
|
|
15
|
-
"dist"
|
|
19
|
+
"dist",
|
|
20
|
+
"templates"
|
|
16
21
|
],
|
|
17
22
|
"scripts": {
|
|
18
23
|
"build": "tsc",
|
|
@@ -22,7 +27,14 @@
|
|
|
22
27
|
},
|
|
23
28
|
"dependencies": {
|
|
24
29
|
"jiti": "^2.6.1",
|
|
25
|
-
"zod": "^3.23.0"
|
|
30
|
+
"zod": "^3.23.0",
|
|
31
|
+
"fastify": "^5.2.0",
|
|
32
|
+
"@fastify/cors": "^10.0.0",
|
|
33
|
+
"@fastify/static": "^8.0.0",
|
|
34
|
+
"commander": "^12.1.0",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"ora": "^8.0.0",
|
|
37
|
+
"glob": "^11.0.0"
|
|
26
38
|
},
|
|
27
39
|
"optionalDependencies": {
|
|
28
40
|
"better-sqlite3": "^12.8.0"
|
|
@@ -31,4 +43,4 @@
|
|
|
31
43
|
"@types/better-sqlite3": "^7.6.13",
|
|
32
44
|
"typescript": "^5.6.0"
|
|
33
45
|
}
|
|
34
|
-
}
|
|
46
|
+
}
|