@yesvara/svara 0.1.0
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/LICENSE +21 -0
- package/README.md +497 -0
- package/dist/chunk-CIESM3BP.mjs +33 -0
- package/dist/chunk-FEA5KIJN.mjs +418 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +328 -0
- package/dist/cli/index.mjs +39 -0
- package/dist/dev-OYGXXK2B.mjs +69 -0
- package/dist/index.d.mts +967 -0
- package/dist/index.d.ts +967 -0
- package/dist/index.js +1976 -0
- package/dist/index.mjs +1502 -0
- package/dist/new-7K4NIDZO.mjs +177 -0
- package/dist/retriever-4QY667XF.mjs +7 -0
- package/examples/01-basic/index.ts +26 -0
- package/examples/02-with-tools/index.ts +73 -0
- package/examples/03-rag-knowledge/index.ts +41 -0
- package/examples/04-multi-channel/index.ts +91 -0
- package/package.json +74 -0
- package/src/app/index.ts +176 -0
- package/src/channels/telegram.ts +122 -0
- package/src/channels/web.ts +118 -0
- package/src/channels/whatsapp.ts +161 -0
- package/src/cli/commands/dev.ts +87 -0
- package/src/cli/commands/new.ts +213 -0
- package/src/cli/index.ts +78 -0
- package/src/core/agent.ts +607 -0
- package/src/core/llm.ts +406 -0
- package/src/core/types.ts +183 -0
- package/src/database/schema.ts +79 -0
- package/src/database/sqlite.ts +239 -0
- package/src/index.ts +94 -0
- package/src/memory/context.ts +49 -0
- package/src/memory/conversation.ts +51 -0
- package/src/rag/chunker.ts +165 -0
- package/src/rag/loader.ts +216 -0
- package/src/rag/retriever.ts +248 -0
- package/src/tools/executor.ts +54 -0
- package/src/tools/index.ts +89 -0
- package/src/tools/registry.ts +44 -0
- package/src/types.ts +131 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
// src/cli/commands/new.ts
|
|
34
|
+
var new_exports = {};
|
|
35
|
+
__export(new_exports, {
|
|
36
|
+
newProject: () => newProject
|
|
37
|
+
});
|
|
38
|
+
async function newProject(options) {
|
|
39
|
+
const { name, provider = "openai", channels = ["web"] } = options;
|
|
40
|
+
const targetDir = import_path.default.resolve(process.cwd(), name);
|
|
41
|
+
console.log(`
|
|
42
|
+
\u2728 Creating SvaraJS project: ${name}
|
|
43
|
+
`);
|
|
44
|
+
try {
|
|
45
|
+
await import_promises.default.access(targetDir);
|
|
46
|
+
console.error(`\u274C Directory "${name}" already exists.`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
await import_promises.default.mkdir(targetDir, { recursive: true });
|
|
51
|
+
await import_promises.default.mkdir(import_path.default.join(targetDir, "src"), { recursive: true });
|
|
52
|
+
await import_promises.default.mkdir(import_path.default.join(targetDir, "docs"), { recursive: true });
|
|
53
|
+
await import_promises.default.mkdir(import_path.default.join(targetDir, "data"), { recursive: true });
|
|
54
|
+
const files = {
|
|
55
|
+
"package.json": generatePackageJson(name),
|
|
56
|
+
"tsconfig.json": generateTsConfig(),
|
|
57
|
+
".env.example": generateEnvExample(provider, channels),
|
|
58
|
+
".gitignore": generateGitignore(),
|
|
59
|
+
"src/index.ts": generateIndexFile(name, provider, channels),
|
|
60
|
+
"docs/README.md": `# ${name} Knowledge Base
|
|
61
|
+
|
|
62
|
+
Add your documents here for RAG.
|
|
63
|
+
`
|
|
64
|
+
};
|
|
65
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
66
|
+
const fullPath = import_path.default.join(targetDir, filePath);
|
|
67
|
+
await import_promises.default.mkdir(import_path.default.dirname(fullPath), { recursive: true });
|
|
68
|
+
await import_promises.default.writeFile(fullPath, content, "utf-8");
|
|
69
|
+
console.log(` \u2713 ${filePath}`);
|
|
70
|
+
}
|
|
71
|
+
if (options.installDeps !== false) {
|
|
72
|
+
console.log("\n\u{1F4E6} Installing dependencies...\n");
|
|
73
|
+
try {
|
|
74
|
+
(0, import_child_process.execSync)("npm install", { cwd: targetDir, stdio: "inherit" });
|
|
75
|
+
} catch {
|
|
76
|
+
console.warn('\n\u26A0\uFE0F Dependency install failed. Run "npm install" manually.\n');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
console.log(`
|
|
80
|
+
\u2705 Project ready!
|
|
81
|
+
|
|
82
|
+
cd ${name}
|
|
83
|
+
cp .env.example .env # Add your API keys
|
|
84
|
+
npm run dev # Start the agent
|
|
85
|
+
|
|
86
|
+
\u{1F4DA} Docs: https://svarajs.dev
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
89
|
+
function generatePackageJson(name) {
|
|
90
|
+
return JSON.stringify({
|
|
91
|
+
name,
|
|
92
|
+
version: "0.1.0",
|
|
93
|
+
private: true,
|
|
94
|
+
scripts: {
|
|
95
|
+
dev: "tsx watch src/index.ts",
|
|
96
|
+
build: "tsc",
|
|
97
|
+
start: "node dist/index.js"
|
|
98
|
+
},
|
|
99
|
+
dependencies: {
|
|
100
|
+
svarajs: "latest",
|
|
101
|
+
dotenv: "^16.4.5"
|
|
102
|
+
},
|
|
103
|
+
devDependencies: {
|
|
104
|
+
"@types/node": "^20.14.2",
|
|
105
|
+
tsx: "^4.15.7",
|
|
106
|
+
typescript: "^5.4.5"
|
|
107
|
+
}
|
|
108
|
+
}, null, 2);
|
|
109
|
+
}
|
|
110
|
+
function generateTsConfig() {
|
|
111
|
+
return JSON.stringify({
|
|
112
|
+
compilerOptions: {
|
|
113
|
+
target: "ES2022",
|
|
114
|
+
module: "CommonJS",
|
|
115
|
+
moduleResolution: "bundler",
|
|
116
|
+
outDir: "dist",
|
|
117
|
+
rootDir: "src",
|
|
118
|
+
strict: true,
|
|
119
|
+
esModuleInterop: true,
|
|
120
|
+
skipLibCheck: true
|
|
121
|
+
},
|
|
122
|
+
include: ["src/**/*"],
|
|
123
|
+
exclude: ["node_modules", "dist"]
|
|
124
|
+
}, null, 2);
|
|
125
|
+
}
|
|
126
|
+
function generateEnvExample(provider, channels) {
|
|
127
|
+
const lines = ["# SvaraJS Environment Variables", ""];
|
|
128
|
+
if (provider === "openai") {
|
|
129
|
+
lines.push("# OpenAI", "OPENAI_API_KEY=sk-...", "");
|
|
130
|
+
} else if (provider === "anthropic") {
|
|
131
|
+
lines.push("# Anthropic", "ANTHROPIC_API_KEY=sk-ant-...", "");
|
|
132
|
+
}
|
|
133
|
+
if (channels.includes("telegram")) {
|
|
134
|
+
lines.push("# Telegram", "TELEGRAM_BOT_TOKEN=...", "");
|
|
135
|
+
}
|
|
136
|
+
if (channels.includes("whatsapp")) {
|
|
137
|
+
lines.push("# WhatsApp", "WA_ACCESS_TOKEN=...", "WA_PHONE_ID=...", "WA_VERIFY_TOKEN=...", "");
|
|
138
|
+
}
|
|
139
|
+
return lines.join("\n");
|
|
140
|
+
}
|
|
141
|
+
function generateIndexFile(name, provider, channels) {
|
|
142
|
+
const modelMap = {
|
|
143
|
+
openai: "gpt-4o",
|
|
144
|
+
anthropic: "claude-opus-4-6",
|
|
145
|
+
ollama: "llama3"
|
|
146
|
+
};
|
|
147
|
+
const channelSetup = channels.map((ch) => {
|
|
148
|
+
if (ch === "web") return `agent.use('web', { port: 3000, cors: true });`;
|
|
149
|
+
if (ch === "telegram") return `agent.use('telegram', { token: process.env.TELEGRAM_BOT_TOKEN! });`;
|
|
150
|
+
if (ch === "whatsapp") return [
|
|
151
|
+
`agent.use('whatsapp', {`,
|
|
152
|
+
` token: process.env.WA_ACCESS_TOKEN!,`,
|
|
153
|
+
` phoneId: process.env.WA_PHONE_ID!,`,
|
|
154
|
+
` verifyToken: process.env.WA_VERIFY_TOKEN!,`,
|
|
155
|
+
`});`
|
|
156
|
+
].join("\n");
|
|
157
|
+
return "";
|
|
158
|
+
}).filter(Boolean).join("\n");
|
|
159
|
+
return `import 'dotenv/config';
|
|
160
|
+
import { svara } from 'svarajs';
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* ${name} \u2014 powered by SvaraJS
|
|
164
|
+
*/
|
|
165
|
+
const agent = svara({
|
|
166
|
+
llm: {
|
|
167
|
+
provider: '${provider}',
|
|
168
|
+
model: '${modelMap[provider] ?? "gpt-4o"}',
|
|
169
|
+
},
|
|
170
|
+
systemPrompt: \`You are a helpful AI assistant called ${name}.
|
|
171
|
+
Be concise, friendly, and always try your best to help.\`,
|
|
172
|
+
memory: {
|
|
173
|
+
type: 'conversation',
|
|
174
|
+
maxMessages: 20,
|
|
175
|
+
},
|
|
176
|
+
verbose: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// \u2500\u2500 Tools \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
180
|
+
agent.tool('get_time', {
|
|
181
|
+
description: 'Get the current date and time',
|
|
182
|
+
parameters: {},
|
|
183
|
+
execute: async () => ({
|
|
184
|
+
datetime: new Date().toISOString(),
|
|
185
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// \u2500\u2500 Channels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
190
|
+
${channelSetup}
|
|
191
|
+
|
|
192
|
+
// \u2500\u2500 Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
193
|
+
agent.start().then(() => {
|
|
194
|
+
console.log('\u{1F680} ${name} is running!');
|
|
195
|
+
});
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
function generateGitignore() {
|
|
199
|
+
return `node_modules/
|
|
200
|
+
dist/
|
|
201
|
+
.env
|
|
202
|
+
data/*.db
|
|
203
|
+
*.log
|
|
204
|
+
`;
|
|
205
|
+
}
|
|
206
|
+
var import_promises, import_path, import_child_process;
|
|
207
|
+
var init_new = __esm({
|
|
208
|
+
"src/cli/commands/new.ts"() {
|
|
209
|
+
"use strict";
|
|
210
|
+
import_promises = __toESM(require("fs/promises"));
|
|
211
|
+
import_path = __toESM(require("path"));
|
|
212
|
+
import_child_process = require("child_process");
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// src/cli/commands/dev.ts
|
|
217
|
+
var dev_exports = {};
|
|
218
|
+
__export(dev_exports, {
|
|
219
|
+
devServer: () => devServer
|
|
220
|
+
});
|
|
221
|
+
async function devServer(options = {}) {
|
|
222
|
+
const entry = options.entry ?? findEntry();
|
|
223
|
+
if (!entry) {
|
|
224
|
+
console.error(`
|
|
225
|
+
\u274C Could not find entry file.
|
|
226
|
+
|
|
227
|
+
Create src/index.ts or specify one:
|
|
228
|
+
svara dev --entry src/app.ts
|
|
229
|
+
`);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
console.log(`
|
|
233
|
+
\u{1F680} SvaraJS Dev Server
|
|
234
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
235
|
+
Entry: ${entry}
|
|
236
|
+
Watch: enabled
|
|
237
|
+
|
|
238
|
+
`);
|
|
239
|
+
const runner = (0, import_child_process2.spawn)(
|
|
240
|
+
"npx",
|
|
241
|
+
["tsx", "watch", "--clear-screen=false", entry],
|
|
242
|
+
{
|
|
243
|
+
stdio: "inherit",
|
|
244
|
+
env: {
|
|
245
|
+
...process.env,
|
|
246
|
+
NODE_ENV: "development",
|
|
247
|
+
...options.port ? { PORT: String(options.port) } : {}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
runner.on("error", (err) => {
|
|
252
|
+
console.error("\n\u274C Dev server error:", err.message);
|
|
253
|
+
console.error('Make sure "tsx" is installed: npm install -D tsx');
|
|
254
|
+
});
|
|
255
|
+
runner.on("exit", (code) => {
|
|
256
|
+
if (code !== 0 && code !== null) {
|
|
257
|
+
process.exit(code);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
261
|
+
process.on(signal, () => {
|
|
262
|
+
runner.kill(signal);
|
|
263
|
+
process.exit(0);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function findEntry() {
|
|
268
|
+
const candidates = [
|
|
269
|
+
"src/index.ts",
|
|
270
|
+
"src/app.ts",
|
|
271
|
+
"src/main.ts",
|
|
272
|
+
"index.ts"
|
|
273
|
+
];
|
|
274
|
+
for (const candidate of candidates) {
|
|
275
|
+
if (import_fs.default.existsSync(import_path2.default.resolve(process.cwd(), candidate))) {
|
|
276
|
+
return candidate;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
var import_child_process2, import_path2, import_fs;
|
|
282
|
+
var init_dev = __esm({
|
|
283
|
+
"src/cli/commands/dev.ts"() {
|
|
284
|
+
"use strict";
|
|
285
|
+
import_child_process2 = require("child_process");
|
|
286
|
+
import_path2 = __toESM(require("path"));
|
|
287
|
+
import_fs = __toESM(require("fs"));
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// src/cli/index.ts
|
|
292
|
+
var import_commander = require("commander");
|
|
293
|
+
var import_module = require("module");
|
|
294
|
+
var import_meta = {};
|
|
295
|
+
var require2 = (0, import_module.createRequire)(import_meta.url);
|
|
296
|
+
var pkg = require2("../../package.json");
|
|
297
|
+
var program = new import_commander.Command();
|
|
298
|
+
program.name("svara").description(pkg.description).version(pkg.version, "-v, --version");
|
|
299
|
+
program.command("new <name>").description("Create a new SvaraJS project").option("--provider <provider>", "LLM provider (openai|anthropic|ollama)", "openai").option("--channel <channels...>", "Channels to include", ["web"]).option("--no-install", "Skip npm install").action(async (name, opts) => {
|
|
300
|
+
const { newProject: newProject2 } = await Promise.resolve().then(() => (init_new(), new_exports));
|
|
301
|
+
await newProject2({
|
|
302
|
+
name,
|
|
303
|
+
provider: opts.provider,
|
|
304
|
+
channels: opts.channel,
|
|
305
|
+
installDeps: opts.install
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
program.command("dev").description("Start development server with hot-reload").option("--entry <file>", "Entry file", "src/index.ts").option("--port <port>", "Override PORT env variable").action(async (opts) => {
|
|
309
|
+
const { devServer: devServer2 } = await Promise.resolve().then(() => (init_dev(), dev_exports));
|
|
310
|
+
await devServer2({
|
|
311
|
+
entry: opts.entry,
|
|
312
|
+
port: opts.port ? parseInt(opts.port, 10) : void 0
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
program.command("build").description("Compile TypeScript to JavaScript").action(async () => {
|
|
316
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
317
|
+
console.log("\u{1F528} Building...");
|
|
318
|
+
try {
|
|
319
|
+
execSync2("npx tsc", { stdio: "inherit" });
|
|
320
|
+
console.log("\u2705 Build complete \u2192 dist/");
|
|
321
|
+
} catch {
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
program.parse(process.argv);
|
|
326
|
+
if (!process.argv.slice(2).length) {
|
|
327
|
+
program.outputHelp();
|
|
328
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
var require2 = createRequire(import.meta.url);
|
|
7
|
+
var pkg = require2("../../package.json");
|
|
8
|
+
var program = new Command();
|
|
9
|
+
program.name("svara").description(pkg.description).version(pkg.version, "-v, --version");
|
|
10
|
+
program.command("new <name>").description("Create a new SvaraJS project").option("--provider <provider>", "LLM provider (openai|anthropic|ollama)", "openai").option("--channel <channels...>", "Channels to include", ["web"]).option("--no-install", "Skip npm install").action(async (name, opts) => {
|
|
11
|
+
const { newProject } = await import("../new-7K4NIDZO.mjs");
|
|
12
|
+
await newProject({
|
|
13
|
+
name,
|
|
14
|
+
provider: opts.provider,
|
|
15
|
+
channels: opts.channel,
|
|
16
|
+
installDeps: opts.install
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
program.command("dev").description("Start development server with hot-reload").option("--entry <file>", "Entry file", "src/index.ts").option("--port <port>", "Override PORT env variable").action(async (opts) => {
|
|
20
|
+
const { devServer } = await import("../dev-OYGXXK2B.mjs");
|
|
21
|
+
await devServer({
|
|
22
|
+
entry: opts.entry,
|
|
23
|
+
port: opts.port ? parseInt(opts.port, 10) : void 0
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
program.command("build").description("Compile TypeScript to JavaScript").action(async () => {
|
|
27
|
+
const { execSync } = await import("child_process");
|
|
28
|
+
console.log("\u{1F528} Building...");
|
|
29
|
+
try {
|
|
30
|
+
execSync("npx tsc", { stdio: "inherit" });
|
|
31
|
+
console.log("\u2705 Build complete \u2192 dist/");
|
|
32
|
+
} catch {
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
program.parse(process.argv);
|
|
37
|
+
if (!process.argv.slice(2).length) {
|
|
38
|
+
program.outputHelp();
|
|
39
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import "./chunk-CIESM3BP.mjs";
|
|
2
|
+
|
|
3
|
+
// src/cli/commands/dev.ts
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
async function devServer(options = {}) {
|
|
8
|
+
const entry = options.entry ?? findEntry();
|
|
9
|
+
if (!entry) {
|
|
10
|
+
console.error(`
|
|
11
|
+
\u274C Could not find entry file.
|
|
12
|
+
|
|
13
|
+
Create src/index.ts or specify one:
|
|
14
|
+
svara dev --entry src/app.ts
|
|
15
|
+
`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
console.log(`
|
|
19
|
+
\u{1F680} SvaraJS Dev Server
|
|
20
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
21
|
+
Entry: ${entry}
|
|
22
|
+
Watch: enabled
|
|
23
|
+
|
|
24
|
+
`);
|
|
25
|
+
const runner = spawn(
|
|
26
|
+
"npx",
|
|
27
|
+
["tsx", "watch", "--clear-screen=false", entry],
|
|
28
|
+
{
|
|
29
|
+
stdio: "inherit",
|
|
30
|
+
env: {
|
|
31
|
+
...process.env,
|
|
32
|
+
NODE_ENV: "development",
|
|
33
|
+
...options.port ? { PORT: String(options.port) } : {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
runner.on("error", (err) => {
|
|
38
|
+
console.error("\n\u274C Dev server error:", err.message);
|
|
39
|
+
console.error('Make sure "tsx" is installed: npm install -D tsx');
|
|
40
|
+
});
|
|
41
|
+
runner.on("exit", (code) => {
|
|
42
|
+
if (code !== 0 && code !== null) {
|
|
43
|
+
process.exit(code);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
47
|
+
process.on(signal, () => {
|
|
48
|
+
runner.kill(signal);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function findEntry() {
|
|
54
|
+
const candidates = [
|
|
55
|
+
"src/index.ts",
|
|
56
|
+
"src/app.ts",
|
|
57
|
+
"src/main.ts",
|
|
58
|
+
"index.ts"
|
|
59
|
+
];
|
|
60
|
+
for (const candidate of candidates) {
|
|
61
|
+
if (fs.existsSync(path.resolve(process.cwd(), candidate))) {
|
|
62
|
+
return candidate;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
devServer
|
|
69
|
+
};
|