@outfitter/presets 0.2.1 → 0.3.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/package.json +2 -2
- package/presets/_base/AGENTS.md.template +3 -0
- package/presets/_base/CLAUDE.md.template +35 -0
- package/presets/_examples/cli-todo/src/program.ts.template +202 -0
- package/presets/_examples/mcp-files/src/mcp.ts.template +181 -0
- package/presets/basic/README.md.template +22 -0
- package/presets/basic/package.json.template +41 -37
- package/presets/basic/src/index.test.ts.template +26 -0
- package/presets/basic/src/index.ts.template +32 -15
- package/presets/basic/tsconfig.json.template +28 -29
- package/presets/cli/CLAUDE.md.template +60 -0
- package/presets/cli/README.md.template +5 -1
- package/presets/cli/package.json.template +47 -44
- package/presets/cli/src/commands/hello.ts.template +26 -0
- package/presets/cli/src/index.test.ts.template +38 -0
- package/presets/cli/src/index.ts.template +2 -0
- package/presets/cli/src/program.ts.template +17 -19
- package/presets/cli/src/types.ts.template +13 -0
- package/presets/cli/tsconfig.json.template +29 -29
- package/presets/daemon/CLAUDE.md.template +53 -0
- package/presets/daemon/README.md.template +6 -7
- package/presets/daemon/package.json.template +50 -47
- package/presets/daemon/src/cli.ts.template +73 -66
- package/presets/daemon/src/daemon-main.ts.template +56 -55
- package/presets/daemon/src/daemon.ts.template +7 -3
- package/presets/daemon/src/index.test.ts.template +9 -0
- package/presets/daemon/tsconfig.json.template +21 -21
- package/presets/full-stack/CLAUDE.md.template +66 -0
- package/presets/full-stack/apps/cli/package.json.template +34 -33
- package/presets/full-stack/apps/cli/src/cli.ts.template +16 -15
- package/presets/full-stack/apps/cli/src/index.test.ts.template +12 -11
- package/presets/full-stack/apps/cli/tsconfig.json.template +32 -32
- package/presets/full-stack/apps/mcp/package.json.template +35 -34
- package/presets/full-stack/apps/mcp/src/index.test.ts.template +12 -11
- package/presets/full-stack/apps/mcp/src/mcp.ts.template +10 -10
- package/presets/full-stack/apps/mcp/src/server.ts.template +3 -2
- package/presets/full-stack/apps/mcp/tsconfig.json.template +32 -32
- package/presets/full-stack/package.json.template +20 -14
- package/presets/full-stack/packages/core/package.json.template +31 -30
- package/presets/full-stack/packages/core/src/handlers.ts.template +29 -24
- package/presets/full-stack/packages/core/src/index.test.ts.template +23 -21
- package/presets/full-stack/packages/core/src/types.ts.template +11 -8
- package/presets/full-stack/packages/core/tsconfig.json.template +29 -29
- package/presets/library/CLAUDE.md.template +68 -0
- package/presets/library/bunup.config.ts.template +16 -16
- package/presets/library/package.json.template +51 -50
- package/presets/library/src/handlers.ts.template +51 -27
- package/presets/library/src/index.test.ts.template +40 -29
- package/presets/library/src/types.ts.template +14 -8
- package/presets/library/tsconfig.json.template +29 -29
- package/presets/mcp/CLAUDE.md.template +97 -0
- package/presets/mcp/README.md.template +12 -9
- package/presets/mcp/package.json.template +48 -44
- package/presets/mcp/src/index.test.ts.template +49 -0
- package/presets/mcp/src/index.ts.template +2 -0
- package/presets/mcp/src/mcp.ts.template +16 -16
- package/presets/mcp/src/server.ts.template +8 -1
- package/presets/mcp/src/tools/hello.ts.template +48 -0
- package/presets/mcp/tsconfig.json.template +21 -21
- package/presets/minimal/README.md.template +22 -0
- package/presets/minimal/package.json.template +47 -44
- package/presets/minimal/src/index.test.ts.template +19 -0
- package/presets/minimal/src/index.ts.template +10 -15
- package/presets/minimal/tsconfig.json.template +28 -29
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ESNext"],
|
|
8
|
+
"types": ["@types/bun"],
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"rootDir": "./src",
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"sourceMap": true,
|
|
21
|
+
"outDir": "./dist",
|
|
22
|
+
"rootDir": "./src",
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
"esModuleInterop": true,
|
|
25
|
+
"forceConsistentCasingInFileNames": true,
|
|
26
|
+
"isolatedModules": true,
|
|
27
|
+
"verbatimModuleSyntax": true,
|
|
28
|
+
"skipLibCheck": true,
|
|
29
|
+
"resolveJsonModule": true
|
|
30
|
+
},
|
|
31
|
+
"include": ["src/**/*"],
|
|
32
|
+
"exclude": ["node_modules", "dist", "src/**/*.test.ts"]
|
|
34
33
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Bun-first TypeScript CLI. Tests before code. Result types, not exceptions.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun run build # Build CLI + library to dist/
|
|
9
|
+
bun run dev # Watch mode (auto-restart on changes)
|
|
10
|
+
bun run test # Run tests
|
|
11
|
+
bun run typecheck # TypeScript validation
|
|
12
|
+
bun run check # Lint + format check
|
|
13
|
+
bun run lint:fix # Auto-fix lint issues
|
|
14
|
+
bun run format # Auto-fix formatting
|
|
15
|
+
bun run verify:ci # Full CI validation (typecheck + check + build + test)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
CLI application built with Commander and `@outfitter/cli`.
|
|
21
|
+
|
|
22
|
+
### Project Structure
|
|
23
|
+
|
|
24
|
+
- `src/cli.ts` — Entry point, creates and runs the program
|
|
25
|
+
- `src/program.ts` — Command registration and wiring
|
|
26
|
+
- `src/commands/` — Command handlers (pure functions returning `Result<T, E>`)
|
|
27
|
+
- `src/types.ts` — Zod schemas and TypeScript interfaces
|
|
28
|
+
|
|
29
|
+
### Handler Contract
|
|
30
|
+
|
|
31
|
+
All domain logic uses handlers returning `Result<T, E>`:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
function handler(
|
|
35
|
+
input: Input,
|
|
36
|
+
ctx: HandlerContext
|
|
37
|
+
): Promise<Result<Output, Error>>;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
CLI commands are thin adapters over shared handlers. Use `runHandler()` from `@outfitter/cli/envelope` to wrap handler results in output envelopes.
|
|
41
|
+
|
|
42
|
+
### Adding a Command
|
|
43
|
+
|
|
44
|
+
1. Define types and Zod schema in `src/types.ts`
|
|
45
|
+
2. Create handler in `src/commands/<name>.ts` returning `Result<T, E>`
|
|
46
|
+
3. Wire command in `src/program.ts` using the CommandBuilder pattern
|
|
47
|
+
4. Add tests in `src/<name>.test.ts`
|
|
48
|
+
|
|
49
|
+
## Development Principles
|
|
50
|
+
|
|
51
|
+
- **TDD-First** — Write the test before the code (Red / Green / Refactor)
|
|
52
|
+
- **Result Types** — Handlers return `Result<T, E>`, not exceptions
|
|
53
|
+
- **Bun-First** — Use Bun-native APIs before npm packages
|
|
54
|
+
- **Strict TypeScript** — No `any`, no `as` casts; narrow instead of assert
|
|
55
|
+
|
|
56
|
+
## Testing
|
|
57
|
+
|
|
58
|
+
- Runner: Bun test runner
|
|
59
|
+
- Files: `src/*.test.ts`
|
|
60
|
+
- Run: `bun test` or `bun run test`
|
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"{{binName}}": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "bun build src/cli.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
|
|
20
|
+
"dev": "bun --watch src/cli.ts",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"check": "ultracite check",
|
|
23
|
+
"verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
|
|
24
|
+
"test": "bun test",
|
|
25
|
+
"test:watch": "bun test --watch",
|
|
26
|
+
"lint": "oxlint .",
|
|
27
|
+
"lint:fix": "oxlint --fix .",
|
|
28
|
+
"format": "oxfmt --write .",
|
|
29
|
+
"clean:artifacts": "rm -rf dist .turbo"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@outfitter/cli": "workspace:*",
|
|
33
|
+
"@outfitter/contracts": "workspace:*",
|
|
34
|
+
"@outfitter/logging": "workspace:*",
|
|
35
|
+
"@outfitter/types": "workspace:*",
|
|
36
|
+
"commander": "catalog:",
|
|
37
|
+
"zod": "catalog:"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {},
|
|
40
|
+
"outfitter": {
|
|
41
|
+
"template": {
|
|
42
|
+
"kind": "runnable",
|
|
43
|
+
"placement": "apps",
|
|
44
|
+
"surfaces": [
|
|
45
|
+
"cli"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
46
49
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Result,
|
|
3
|
+
ValidationError,
|
|
4
|
+
type HandlerContext,
|
|
5
|
+
} from "@outfitter/contracts";
|
|
6
|
+
import { createLogger } from "@outfitter/logging";
|
|
7
|
+
|
|
8
|
+
import { greetingInputSchema, type GreetingOutput } from "../types.js";
|
|
9
|
+
|
|
10
|
+
const logger = createLogger({ name: "{{binName}}" });
|
|
11
|
+
|
|
12
|
+
export async function greet(
|
|
13
|
+
input: unknown,
|
|
14
|
+
ctx: HandlerContext
|
|
15
|
+
): Promise<Result<GreetingOutput, ValidationError>> {
|
|
16
|
+
const parsed = greetingInputSchema.safeParse(input);
|
|
17
|
+
if (!parsed.success) {
|
|
18
|
+
return Result.err(
|
|
19
|
+
new ValidationError({ message: "Invalid greeting input", field: "name" })
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const message = `Hello, ${parsed.data.name}!`;
|
|
24
|
+
logger.info(message, { requestId: ctx.requestId });
|
|
25
|
+
return Result.ok({ message });
|
|
26
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { createContext } from "@outfitter/contracts";
|
|
4
|
+
|
|
5
|
+
import { greet } from "./commands/hello.js";
|
|
6
|
+
import { program } from "./index.js";
|
|
7
|
+
|
|
8
|
+
describe("program", () => {
|
|
9
|
+
test("registers the hello command", () => {
|
|
10
|
+
expect(program.program.name()).toBe("{{binName}}");
|
|
11
|
+
|
|
12
|
+
const registered = program.program.commands.some(
|
|
13
|
+
(cmd) => cmd.name() === "hello"
|
|
14
|
+
);
|
|
15
|
+
expect(registered).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("greet", () => {
|
|
20
|
+
test("returns greeting for valid input", async () => {
|
|
21
|
+
const ctx = createContext({ cwd: process.cwd(), env: process.env });
|
|
22
|
+
const result = await greet({ name: "Outfitter" }, ctx);
|
|
23
|
+
|
|
24
|
+
expect(result.isOk()).toBe(true);
|
|
25
|
+
if (result.isErr()) return;
|
|
26
|
+
expect(result.value.message).toBe("Hello, Outfitter!");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("returns validation error for empty name", async () => {
|
|
30
|
+
const ctx = createContext({ cwd: process.cwd(), env: process.env });
|
|
31
|
+
const result = await greet({ name: "" }, ctx);
|
|
32
|
+
|
|
33
|
+
expect(result.isErr()).toBe(true);
|
|
34
|
+
if (result.isErr()) {
|
|
35
|
+
expect(result.error.name).toBe("ValidationError");
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -3,29 +3,27 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { command, createCLI } from "@outfitter/cli/command";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { runHandler } from "@outfitter/cli/envelope";
|
|
7
|
+
import { createContext } from "@outfitter/contracts";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
import { greet } from "./commands/hello.js";
|
|
10
10
|
|
|
11
11
|
export const program = createCLI({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
name: "{{binName}}",
|
|
13
|
+
version: "{{version}}",
|
|
14
|
+
description: "{{description}}",
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
const verbose = verbosePreset();
|
|
18
|
-
|
|
19
17
|
program.register(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
command("hello [name]")
|
|
19
|
+
.description("Say hello")
|
|
20
|
+
.action(async ({ args }) => {
|
|
21
|
+
await runHandler({
|
|
22
|
+
command: "hello",
|
|
23
|
+
input: { name: args[0] ?? "World" },
|
|
24
|
+
contextFactory: () =>
|
|
25
|
+
createContext({ cwd: process.cwd(), env: process.env }),
|
|
26
|
+
handler: greet,
|
|
27
|
+
});
|
|
28
|
+
})
|
|
31
29
|
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ZodType, z } from "zod";
|
|
2
|
+
|
|
3
|
+
export interface GreetingInput {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const greetingInputSchema: ZodType<GreetingInput> = z.object({
|
|
8
|
+
name: z.string().min(1, "name is required"),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export interface GreetingOutput {
|
|
12
|
+
readonly message: string;
|
|
13
|
+
}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ESNext"],
|
|
8
|
+
"types": ["@types/bun"],
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"declarationMap": true,
|
|
21
|
+
"sourceMap": true,
|
|
22
|
+
"outDir": "./dist",
|
|
23
|
+
"rootDir": "./src",
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"verbatimModuleSyntax": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist"]
|
|
34
34
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Bun-first TypeScript daemon. Tests before code. Result types, not exceptions.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun run build # Build CLI + daemon to dist/
|
|
9
|
+
bun run dev # Watch mode (foreground)
|
|
10
|
+
bun run dev:daemon # Watch mode (foreground, explicit)
|
|
11
|
+
bun run test # Run tests
|
|
12
|
+
bun run typecheck # TypeScript validation
|
|
13
|
+
bun run check # Lint + format check
|
|
14
|
+
bun run lint:fix # Auto-fix lint issues
|
|
15
|
+
bun run format # Auto-fix formatting
|
|
16
|
+
bun run verify:ci # Full CI validation (typecheck + check + build + test)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
Background daemon with CLI control interface, built with `@outfitter/daemon` and `@outfitter/cli`.
|
|
22
|
+
|
|
23
|
+
### Project Structure
|
|
24
|
+
|
|
25
|
+
- `src/daemon.ts` — Daemon entry point (background process)
|
|
26
|
+
- `src/daemon-main.ts` — Daemon lifecycle and HTTP server (Unix socket)
|
|
27
|
+
- `src/cli.ts` — CLI control commands (start, stop, status)
|
|
28
|
+
- `src/index.ts` — Library re-exports
|
|
29
|
+
|
|
30
|
+
### Daemon Lifecycle
|
|
31
|
+
|
|
32
|
+
The daemon uses `acquireDaemonLock()` and `releaseDaemonLock()` from `@outfitter/daemon` with `Bun.serve()` on a Unix socket:
|
|
33
|
+
|
|
34
|
+
- **start** — Checks liveness, spawns background process (or runs in foreground with `--foreground`)
|
|
35
|
+
- **stop** — Checks liveness, then sends POST to `/shutdown` endpoint
|
|
36
|
+
- **status** — Checks liveness via `isDaemonAlive()`, then fetches `/health` for uptime and version
|
|
37
|
+
|
|
38
|
+
### Handler Contract
|
|
39
|
+
|
|
40
|
+
CLI commands and daemon operations use handlers returning `Result<T, E>`. Use structured logging via `@outfitter/logging` instead of `console.error`.
|
|
41
|
+
|
|
42
|
+
## Development Principles
|
|
43
|
+
|
|
44
|
+
- **TDD-First** — Write the test before the code (Red / Green / Refactor)
|
|
45
|
+
- **Result Types** — Handlers return `Result<T, E>`, not exceptions
|
|
46
|
+
- **Bun-First** — Use Bun-native APIs before npm packages
|
|
47
|
+
- **Strict TypeScript** — No `any`, no `as` casts; narrow instead of assert
|
|
48
|
+
|
|
49
|
+
## Testing
|
|
50
|
+
|
|
51
|
+
- Runner: Bun test runner
|
|
52
|
+
- Files: `src/*.test.ts`
|
|
53
|
+
- Run: `bun test` or `bun run test`
|
|
@@ -4,12 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
A background daemon with CLI control interface.
|
|
6
6
|
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
bun add {{packageName}}
|
|
11
|
-
```
|
|
12
|
-
|
|
13
7
|
## Usage
|
|
14
8
|
|
|
15
9
|
```bash
|
|
@@ -52,7 +46,12 @@ Gracefully shuts down the daemon.
|
|
|
52
46
|
# Install dependencies
|
|
53
47
|
bun install
|
|
54
48
|
|
|
55
|
-
# Run
|
|
49
|
+
# Run from source (foreground only — background spawn requires a build)
|
|
50
|
+
bun run src/cli.ts start --foreground
|
|
51
|
+
bun run src/cli.ts status
|
|
52
|
+
bun run src/cli.ts stop
|
|
53
|
+
|
|
54
|
+
# Run daemon in foreground (via dev script)
|
|
56
55
|
bun run dev
|
|
57
56
|
|
|
58
57
|
# Build
|
|
@@ -1,49 +1,52 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"{{binName}}": "./dist/cli.js",
|
|
8
|
+
"{{binName}}d": "./dist/daemon.js"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun build src/cli.ts src/daemon.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
|
|
21
|
+
"dev": "bun --watch src/daemon.ts -- --foreground",
|
|
22
|
+
"dev:daemon": "bun --watch src/daemon.ts -- --foreground",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"check": "ultracite check",
|
|
25
|
+
"verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
|
|
26
|
+
"test": "bun test",
|
|
27
|
+
"test:watch": "bun test --watch",
|
|
28
|
+
"lint": "oxlint .",
|
|
29
|
+
"lint:fix": "oxlint --fix .",
|
|
30
|
+
"format": "oxfmt --write .",
|
|
31
|
+
"clean:artifacts": "rm -rf dist .turbo"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@outfitter/cli": "workspace:*",
|
|
35
|
+
"@outfitter/contracts": "workspace:*",
|
|
36
|
+
"@outfitter/daemon": "workspace:*",
|
|
37
|
+
"@outfitter/logging": "workspace:*",
|
|
38
|
+
"@outfitter/types": "workspace:*",
|
|
39
|
+
"commander": "catalog:"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {},
|
|
42
|
+
"outfitter": {
|
|
43
|
+
"template": {
|
|
44
|
+
"kind": "runnable",
|
|
45
|
+
"placement": "apps",
|
|
46
|
+
"surfaces": [
|
|
47
|
+
"cli",
|
|
48
|
+
"daemon"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
49
52
|
}
|