feat: cli 包完整 build 支持(tsc emit + Node 兼容)

- tsconfig: 启用 emit (rootDir/outDir/composite), 添加 project references
- shebang: bun → node
- bin: src/index.ts → dist/index.js
- import.meta.dir → import.meta.dirname (去掉 Bun 专有 API)
- prompts 目录移到包根, src/dist 路径统一
- 修复 exactOptionalPropertyTypes 类型错误

Fixes #58
This commit is contained in:
2026-06-03 02:29:01 +00:00
parent 234bd0d611
commit 5f562cbc5a
10 changed files with 344 additions and 18 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "0.2.0",
"type": "module",
"bin": {
"ocas": "src/index.ts"
"ocas": "dist/index.js"
},
"dependencies": {
"@ocas/core": "workspace:*",
+7 -7
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bun
#!/usr/bin/env node
import { existsSync, readFileSync } from "node:fs";
import { homedir } from "node:os";
@@ -91,7 +91,7 @@ const { flags, positional } = parseArgs(process.argv.slice(2));
// --- Handle --version early ---
if (flags.version === true) {
const pkgPath = join(import.meta.dir, "..", "package.json");
const pkgPath = join(import.meta.dirname, "..", "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
process.stdout.write(`${pkg.version}\n`);
process.exit(0);
@@ -1033,8 +1033,8 @@ async function cmdList(_args: string[]): Promise<void> {
// Get all entries of the requested type (no limit/offset yet) and filter.
const allOfType = store.cas.listByType(typeHash, {
sort: opts.sort,
desc: opts.desc,
...(opts.sort !== undefined && { sort: opts.sort }),
...(opts.desc !== undefined && { desc: opts.desc }),
});
const filtered: ListEntry[] = allOfType.filter((e) =>
intersection!.has(e.hash),
@@ -1064,7 +1064,7 @@ async function cmdListSchema(_args: string[]): Promise<void> {
}
function printUsage(): void {
const pkgPath = join(import.meta.dir, "..", "package.json");
const pkgPath = join(import.meta.dirname, "..", "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
console.log(`\
Usage: ocas [--home <path>] [--json] <command> [args]
@@ -1230,7 +1230,7 @@ switch (cmd) {
switch (sub) {
case "usage": {
const content = readFileSync(
join(import.meta.dir, "prompts", "usage.md"),
join(import.meta.dirname, "..", "prompts", "usage.md"),
"utf-8",
);
process.stdout.write(content);
@@ -1238,7 +1238,7 @@ switch (cmd) {
}
case "setup": {
const content = readFileSync(
join(import.meta.dir, "prompts", "setup.md"),
join(import.meta.dirname, "..", "prompts", "setup.md"),
"utf-8",
);
process.stdout.write(content);
+1 -1
View File
@@ -12,7 +12,7 @@ const pkgPath = resolve(import.meta.dir, "../package.json");
describe("ocas binary", () => {
test("T1: ocas bin entry exists in package.json", async () => {
const pkg = await Bun.file(pkgPath).json();
expect(pkg.bin.ocas).toBe("src/index.ts");
expect(pkg.bin.ocas).toBe("dist/index.js");
});
test("T2: no legacy bin entries (json-cas, ucas)", async () => {
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { join } from "node:path";
const usagePath = join(import.meta.dir, "usage.md");
const usagePath = join(import.meta.dir, "..", "prompts", "usage.md");
describe("usage.md doc cleanup (D)", () => {
test("D3. usage.md does not reference legacy openStoreAndVarStore / createVariableStore", () => {
+8 -5
View File
@@ -1,10 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": false,
"declaration": false,
"declarationMap": false,
"noEmit": true
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"]
"include": ["src"],
"exclude": ["src/**/*.test.ts"],
"references": [
{ "path": "../core" },
{ "path": "../fs" }
]
}