Compare commits

...

6 Commits

Author SHA1 Message Date
xiaoju ade6227ffe feat: add uwf cas reindex command
Rebuilds _index from all .bin nodes. Use after upgrading to json-cas 0.2.0
on an existing CAS directory.
2026-05-18 14:24:23 +00:00
xiaomo 13789e2c66 Merge pull request 'refactor: use listByType for schema list, upgrade json-cas to 0.2.0' (#333) from refactor/use-list-by-type into main 2026-05-18 14:18:16 +00:00
xiaoju 6758adc1d5 refactor: use listByType for schema list, upgrade json-cas to 0.2.0
Replace O(n) full CAS scan with O(1) type-index lookup.

Refs #328
2026-05-18 14:16:15 +00:00
xiaomo 7c12015855 Merge pull request 'refactor: merge cas get/cat into get, default hides timestamp' (#332) from refactor/merge-cas-get-cat into main 2026-05-18 14:03:50 +00:00
xiaoju 0f6859678c refactor: merge cas get/cat into get, default hides timestamp
- Remove `cas cat` command
- `cas get` now returns {type, payload} by default
- Add `--timestamp` flag to include timestamp

Refs #328
2026-05-18 14:03:10 +00:00
xiaomo 84798510b0 Merge pull request 'refactor: remove table output format, keep json and yaml only' (#331) from refactor/remove-table-format into main 2026-05-18 13:59:12 +00:00
5 changed files with 38 additions and 36 deletions
+2 -2
View File
@@ -11,8 +11,8 @@
"uwf": "./src/cli.ts"
},
"dependencies": {
"@uncaged/json-cas": "^0.1.3",
"@uncaged/json-cas-fs": "^0.1.2",
"@uncaged/json-cas": "^0.2.0",
"@uncaged/json-cas-fs": "^0.2.0",
"@uncaged/uwf-agent-kit": "workspace:^",
"@uncaged/uwf-moderator": "workspace:^",
"@uncaged/uwf-protocol": "workspace:^",
+15 -16
View File
@@ -12,10 +12,10 @@ import {
import { cmdWorkflowList, cmdWorkflowPut, cmdWorkflowShow } from "./commands/workflow.js";
import { cmdSetup, cmdSetupInteractive } from "./commands/setup.js";
import {
cmdCasCat,
cmdCasGet,
cmdCasHas,
cmdCasPut,
cmdCasReindex,
cmdCasRefs,
cmdCasSchemaGet,
cmdCasSchemaList,
@@ -185,24 +185,13 @@ const cas = program.command("cas").description("Content-addressable storage oper
cas
.command("get")
.description("Read a CAS node as JSON")
.description("Read a CAS node (type + payload; use --timestamp to include timestamp)")
.argument("<hash>", "CAS hash (13 char)")
.action((hash: string) => {
.option("--timestamp", "Include timestamp in output")
.action((hash: string, opts: { timestamp?: boolean }) => {
const storageRoot = resolveStorageRoot();
runAction(async () => {
writeOutput(await cmdCasGet(storageRoot, hash));
});
});
cas
.command("cat")
.description("Output a CAS node (--payload for payload only)")
.argument("<hash>", "CAS hash (13 char)")
.option("--payload", "Output only the payload")
.action((hash: string, opts: { payload?: boolean }) => {
const storageRoot = resolveStorageRoot();
runAction(async () => {
writeOutput(await cmdCasCat(storageRoot, hash, opts));
writeOutput(await cmdCasGet(storageRoot, hash, opts));
});
});
@@ -251,6 +240,16 @@ cas
});
});
cas
.command("reindex")
.description("Rebuild type index from all CAS nodes")
.action(() => {
const storageRoot = resolveStorageRoot();
runAction(async () => {
writeOutput(await cmdCasReindex(storageRoot));
});
});
const casSchema = cas.command("schema").description("CAS schema operations");
casSchema
+18 -15
View File
@@ -28,26 +28,18 @@ function readJsonArg(fileOrInline: string): unknown {
export async function cmdCasGet(
storageRoot: string,
hash: string,
opts: { timestamp?: boolean },
): Promise<unknown> {
const store = openStore(storageRoot);
const node = store.get(hash);
if (node === null) {
throw new Error(`Node not found: ${hash}`);
}
return node;
}
export async function cmdCasCat(
storageRoot: string,
hash: string,
opts: { payload?: boolean },
): Promise<unknown> {
const store = openStore(storageRoot);
const node = store.get(hash);
if (node === null) {
throw new Error(`Node not found: ${hash}`);
if (opts.timestamp) {
return node;
}
return opts.payload ? node.payload : node;
const { timestamp: _, ...rest } = node as Record<string, unknown>;
return rest;
}
export async function cmdCasPut(
@@ -108,10 +100,10 @@ export async function cmdCasSchemaList(
// Include meta-schema itself
entries.push({ hash: metaHash, title: "(meta-schema)" });
for (const hash of store.list()) {
for (const hash of store.listByType(metaHash)) {
if (hash === metaHash) continue;
const node = store.get(hash);
if (node !== null && node.type === metaHash) {
if (node !== null) {
const schema = node.payload as JSONSchema;
const title =
(schema.title as string | undefined) ??
@@ -123,6 +115,17 @@ export async function cmdCasSchemaList(
return entries;
}
export async function cmdCasReindex(
storageRoot: string,
): Promise<{ status: string }> {
const indexDir = join(storageRoot, "cas", "_index");
const { rmSync } = await import("node:fs");
rmSync(indexDir, { recursive: true, force: true });
// Re-open store to trigger migration rebuild
openStore(storageRoot);
return { status: "reindexed" };
}
export async function cmdCasSchemaGet(
storageRoot: string,
hash: string,
+2 -2
View File
@@ -18,8 +18,8 @@
"test": "bun test"
},
"dependencies": {
"@uncaged/json-cas": "^0.1.3",
"@uncaged/json-cas-fs": "^0.1.2",
"@uncaged/json-cas": "^0.2.0",
"@uncaged/json-cas-fs": "^0.2.0",
"@uncaged/uwf-protocol": "workspace:^",
"dotenv": "^16.6.1",
"yaml": "^2.8.4"
+1 -1
View File
@@ -15,7 +15,7 @@
}
},
"dependencies": {
"@uncaged/json-cas-fs": "^0.1.3"
"@uncaged/json-cas-fs": "^0.2.0"
},
"devDependencies": {
"typescript": "^5.8.3"