Merge pull request 'feat(cli): init generates pnpm workspace with TypeScript senses' (#230) from feat/229-init-workspace-pnpm into main
This commit was merged in pull request #230.
This commit is contained in:
@@ -202,10 +202,12 @@ describe("e2e init", () => {
|
||||
// Verify key files exist
|
||||
expect(existsSync(join(nerveRoot, "nerve.yaml"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "package.json"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "pnpm-workspace.yaml"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "biome.json"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, ".gitignore"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "schema.ts"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "index.js"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "package.json"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "src", "index.ts"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "src", "schema.ts"))).toBe(true);
|
||||
expect(existsSync(join(nerveRoot, "senses", "cpu-usage", "migrations", "0001_init.sql"))).toBe(
|
||||
true,
|
||||
);
|
||||
@@ -213,6 +215,18 @@ describe("e2e init", () => {
|
||||
|
||||
const pkgJson = readFileSync(join(nerveRoot, "package.json"), "utf8");
|
||||
expect(pkgJson).toContain('"@uncaged/nerve-skills": "latest"');
|
||||
expect(pkgJson).toContain('"build": "pnpm -r build"');
|
||||
|
||||
const workspaceYaml = readFileSync(join(nerveRoot, "pnpm-workspace.yaml"), "utf8");
|
||||
expect(workspaceYaml).toContain("workflows/*");
|
||||
expect(workspaceYaml).toContain("senses/*");
|
||||
|
||||
const sensePkgJson = readFileSync(
|
||||
join(nerveRoot, "senses", "cpu-usage", "package.json"),
|
||||
"utf8",
|
||||
);
|
||||
expect(sensePkgJson).toContain("nerve-sense-cpu-usage");
|
||||
expect(sensePkgJson).toContain("esbuild");
|
||||
});
|
||||
|
||||
it("generated nerve.yaml passes validate", { timeout: 10_000 }, async () => {
|
||||
|
||||
@@ -324,12 +324,12 @@ const createSenseCommand = defineCommand({
|
||||
|
||||
process.stdout.write("\nInstalling sense dependencies and building…\n");
|
||||
try {
|
||||
await spawnAsync("pnpm", ["install", "--no-cache"], senseDir);
|
||||
await spawnAsync("pnpm", ["install", "--no-cache", "--ignore-workspace"], senseDir);
|
||||
await spawnAsync("pnpm", ["run", "build"], senseDir);
|
||||
process.stdout.write("✅ Build complete — index.js ready.\n");
|
||||
} catch {
|
||||
process.stdout.write(
|
||||
`⚠️ Build failed. Run manually:\n cd ${senseDir} && pnpm install --no-cache && pnpm run build\n`,
|
||||
`⚠️ Build failed. Run manually:\n cd ${senseDir} && pnpm install --no-cache --ignore-workspace && pnpm run build\n`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ senses:
|
||||
interval: 10s
|
||||
`;
|
||||
|
||||
const PNPM_WORKSPACE_YAML = `packages:
|
||||
- 'workflows/*'
|
||||
- 'senses/*'
|
||||
`;
|
||||
|
||||
const BIOME_JSON = `{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
|
||||
"formatter": {
|
||||
@@ -42,26 +47,32 @@ const BIOME_JSON = `{
|
||||
}
|
||||
`;
|
||||
|
||||
const PACKAGE_JSON = `{
|
||||
"name": "my-nerve-workspace",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@uncaged/nerve-core": "latest",
|
||||
"@uncaged/nerve-daemon": "latest",
|
||||
"@uncaged/nerve-skills": "latest",
|
||||
"drizzle-orm": "latest"
|
||||
const PACKAGE_JSON = `${JSON.stringify(
|
||||
{
|
||||
name: "my-nerve-workspace",
|
||||
version: "0.0.1",
|
||||
private: true,
|
||||
type: "module",
|
||||
scripts: {
|
||||
build: "pnpm -r build",
|
||||
},
|
||||
dependencies: {
|
||||
"@uncaged/nerve-core": "latest",
|
||||
"@uncaged/nerve-daemon": "latest",
|
||||
"@uncaged/nerve-skills": "latest",
|
||||
"drizzle-orm": "latest",
|
||||
},
|
||||
devDependencies: {
|
||||
"@biomejs/biome": "latest",
|
||||
"drizzle-kit": "latest",
|
||||
},
|
||||
pnpm: {
|
||||
onlyBuiltDependencies: ["esbuild"],
|
||||
},
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "latest",
|
||||
"drizzle-kit": "latest"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": ["esbuild"]
|
||||
}
|
||||
}
|
||||
`;
|
||||
null,
|
||||
2,
|
||||
)}\n`;
|
||||
|
||||
const GITIGNORE = `data/
|
||||
logs/
|
||||
@@ -110,9 +121,14 @@ export const cpuUsage = sqliteTable("cpu_usage", {
|
||||
});
|
||||
`;
|
||||
|
||||
const CPU_INDEX_JS = `import { cpus } from "node:os";
|
||||
const CPU_INDEX_TS = `import { cpus } from "node:os";
|
||||
|
||||
export async function compute() {
|
||||
type SenseResult = {
|
||||
signal: { model: string; loadPercent: number; ts: number };
|
||||
workflow: null;
|
||||
};
|
||||
|
||||
export async function compute(): Promise<SenseResult> {
|
||||
const cpuList = cpus();
|
||||
|
||||
let totalIdle = 0;
|
||||
@@ -137,6 +153,24 @@ export async function compute() {
|
||||
}
|
||||
`;
|
||||
|
||||
const CPU_SENSE_PACKAGE_JSON = `${JSON.stringify(
|
||||
{
|
||||
name: "nerve-sense-cpu-usage",
|
||||
private: true,
|
||||
type: "module",
|
||||
scripts: {
|
||||
build:
|
||||
"esbuild src/index.ts --bundle --platform=node --format=esm --outdir=. --out-extension:.js=.js --packages=external",
|
||||
},
|
||||
devDependencies: {
|
||||
esbuild: "^0.27.0",
|
||||
"drizzle-orm": "*",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`;
|
||||
|
||||
const CPU_MIGRATION_SQL = `CREATE TABLE IF NOT EXISTS cpu_usage (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
ts INTEGER NOT NULL,
|
||||
@@ -294,14 +328,17 @@ async function runInitWorkspace(force: boolean, skipInstall = false): Promise<vo
|
||||
|
||||
mkdirSync(join(nerveRoot, "data"), { recursive: true });
|
||||
mkdirSync(join(nerveRoot, "data", "senses"), { recursive: true });
|
||||
mkdirSync(join(nerveRoot, "senses", "cpu-usage", "src"), { recursive: true });
|
||||
mkdirSync(join(nerveRoot, "senses", "cpu-usage", "migrations"), { recursive: true });
|
||||
|
||||
writeFile(join(nerveRoot, "nerve.yaml"), NERVE_YAML);
|
||||
writeFile(join(nerveRoot, "package.json"), PACKAGE_JSON);
|
||||
writeFile(join(nerveRoot, "pnpm-workspace.yaml"), PNPM_WORKSPACE_YAML);
|
||||
writeFile(join(nerveRoot, "biome.json"), BIOME_JSON);
|
||||
writeFile(join(nerveRoot, ".gitignore"), GITIGNORE);
|
||||
writeFile(join(nerveRoot, "senses", "cpu-usage", "schema.ts"), CPU_SCHEMA_TS);
|
||||
writeFile(join(nerveRoot, "senses", "cpu-usage", "index.js"), CPU_INDEX_JS);
|
||||
writeFile(join(nerveRoot, "senses", "cpu-usage", "package.json"), CPU_SENSE_PACKAGE_JSON);
|
||||
writeFile(join(nerveRoot, "senses", "cpu-usage", "src", "index.ts"), CPU_INDEX_TS);
|
||||
writeFile(join(nerveRoot, "senses", "cpu-usage", "src", "schema.ts"), CPU_SCHEMA_TS);
|
||||
writeFile(
|
||||
join(nerveRoot, "senses", "cpu-usage", "migrations", "0001_init.sql"),
|
||||
CPU_MIGRATION_SQL,
|
||||
@@ -319,6 +356,13 @@ async function runInitWorkspace(force: boolean, skipInstall = false): Promise<vo
|
||||
);
|
||||
}
|
||||
|
||||
process.stdout.write("Building senses…\n");
|
||||
try {
|
||||
await runCommand("pnpm", ["run", "build"], nerveRoot);
|
||||
} catch {
|
||||
process.stdout.write(`⚠️ Build failed. Try manually:\n cd ${nerveRoot} && pnpm run build\n`);
|
||||
}
|
||||
|
||||
if (!(await verifyNodeSqlite())) {
|
||||
process.stdout.write(
|
||||
"⚠️ Built-in SQLite (node:sqlite) is not available in this Node.js build. " +
|
||||
|
||||
Reference in New Issue
Block a user