Merge pull request 'feat: rebrand json-cas → OCAS' (#9) from feat/rebranding into main
This commit was merged in pull request #9.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
|
||||
"changelog": ["@changesets/changelog-github", { "repo": "uncaged/json-cas" }],
|
||||
"changelog": ["@changesets/changelog-github", { "repo": "shazhou-ww/ocas" }],
|
||||
"commit": false,
|
||||
"fixed": [["@uncaged/*"]],
|
||||
"fixed": [["@ocas/*"]],
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# CLAUDE.md — json-cas
|
||||
# CLAUDE.md — ocas
|
||||
|
||||
Self-describing content-addressable storage with JSON Schema typed nodes.
|
||||
|
||||
@@ -8,9 +8,9 @@ Monorepo with 4 packages under `packages/`:
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `json-cas` | Core CAS engine — hashing, schema, store, verify, bootstrap |
|
||||
| `json-cas-fs` | Filesystem-backed CAS store |
|
||||
| `cli-json-cas` | CLI tool |
|
||||
| `ocas` | Core CAS engine — hashing, schema, store, verify, bootstrap |
|
||||
| `ocas-fs` | Filesystem-backed CAS store |
|
||||
| `cli` | CLI tool |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
@@ -19,7 +19,7 @@ Monorepo with 4 packages under `packages/`:
|
||||
- **Build:** `tsc --build` (composite project references)
|
||||
- **Test:** `bun test`
|
||||
- **Lint/Format:** Biome (`biome check .` / `biome format --write .`)
|
||||
- **Publish:** Changesets → npmjs (`@uncaged/*`)
|
||||
- **Publish:** Changesets → npmjs (`@ocas/*`)
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -41,7 +41,7 @@ bun run format # Biome format (auto-fix)
|
||||
|
||||
### Biome Rules
|
||||
|
||||
- `noConsole: "error"` globally (except `cli-json-cas`)
|
||||
- `noConsole: "error"` globally (except `cli`)
|
||||
- Recommended ruleset enabled
|
||||
- Auto-organize imports via `assist.actions.source.organizeImports`
|
||||
- Indent: 2 spaces
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# json-cas
|
||||
# ocas
|
||||
|
||||
Self-describing content-addressable storage with JSON Schema typed nodes.
|
||||
|
||||
## Overview
|
||||
|
||||
json-cas is a monorepo for storing and validating JSON data in a content-addressable store (CAS). Each node has a typed payload: its `type` field is the hash of a JSON Schema node that describes the payload shape. Hashes are 13-character Crockford Base32 strings derived from XXH64 over deterministic CBOR encoding.
|
||||
ocas is a monorepo for storing and validating JSON data in a content-addressable store (CAS). Each node has a typed payload: its `type` field is the hash of a JSON Schema node that describes the payload shape. Hashes are 13-character Crockford Base32 strings derived from XXH64 over deterministic CBOR encoding.
|
||||
|
||||
A bootstrap meta-schema is stored as a self-referencing seed node (`type === hash`). All other schemas are registered as nodes typed by that meta-schema. Payloads can reference other nodes via `format: "cas_ref"` fields; the library provides traversal, reference extraction, and integrity verification.
|
||||
|
||||
@@ -14,39 +14,39 @@ Use the in-memory store for tests and embedded apps, the filesystem store for pe
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ cli-json-cas │
|
||||
│ cli-ocas │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ json-cas-fs │
|
||||
│ ocas-fs │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ json-cas │ (core)
|
||||
│ ocas │ (core)
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
| Layer | Package | Role |
|
||||
|-------|---------|------|
|
||||
| Core | `@uncaged/json-cas` | Hashing, schemas, stores, verify, bootstrap |
|
||||
| Storage | `@uncaged/json-cas-fs` | Filesystem-backed `Store` |
|
||||
| CLI | `@uncaged/cli-json-cas` | `ucas` command-line tool |
|
||||
| Core | `@ocas/core` | Hashing, schemas, stores, verify, bootstrap |
|
||||
| Storage | `@ocas/fs` | Filesystem-backed `Store` |
|
||||
| CLI | `@ocas/cli` | `ocas` command-line tool |
|
||||
|
||||
## Packages
|
||||
|
||||
| Package | Description | Type |
|
||||
|---------|-------------|------|
|
||||
| [`@uncaged/json-cas`](packages/json-cas/README.md) | Core CAS engine — hashing, schema, store, verify, bootstrap | lib |
|
||||
| [`@uncaged/json-cas-fs`](packages/json-cas-fs/README.md) | Filesystem-backed CAS store | lib |
|
||||
| [`@uncaged/cli-json-cas`](packages/cli-json-cas/README.md) | CLI tool (`ucas` binary) | cli |
|
||||
| [`@ocas/core`](packages/ocas/README.md) | Core CAS engine — hashing, schema, store, verify, bootstrap | lib |
|
||||
| [`@ocas/fs`](packages/ocas-fs/README.md) | Filesystem-backed CAS store | lib |
|
||||
| [`@ocas/cli`](packages/cli-ocas/README.md) | CLI tool (`ocas` binary) | cli |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
git clone <repo-url>
|
||||
cd json-cas
|
||||
cd ocas
|
||||
bun install --no-cache
|
||||
bun run build
|
||||
```
|
||||
@@ -57,7 +57,7 @@ import {
|
||||
createMemoryStore,
|
||||
putSchema,
|
||||
validate,
|
||||
} from "@uncaged/json-cas";
|
||||
} from "@ocas/core";
|
||||
|
||||
const store = createMemoryStore();
|
||||
await bootstrap(store);
|
||||
@@ -77,20 +77,20 @@ console.log(validate(store, node!)); // true
|
||||
For a persistent store:
|
||||
|
||||
```typescript
|
||||
import { createFsStore } from "@uncaged/json-cas-fs";
|
||||
import { bootstrap } from "@uncaged/json-cas";
|
||||
import { createFsStore } from "@ocas/fs";
|
||||
import { bootstrap } from "@ocas/core";
|
||||
|
||||
const store = createFsStore("/path/to/store");
|
||||
await bootstrap(store);
|
||||
```
|
||||
|
||||
Or use the CLI (see [CLI Reference](#cli-reference) and [`packages/cli-json-cas/README.md`](packages/cli-json-cas/README.md)).
|
||||
Or use the CLI (see [CLI Reference](#cli-reference) and [`packages/cli-ocas/README.md`](packages/cli-ocas/README.md)).
|
||||
|
||||
## CLI Reference
|
||||
|
||||
Binary: `ucas` (from `@uncaged/cli-json-cas`; legacy alias `json-cas` is deprecated). Default store:
|
||||
`~/.uncaged/json-cas`. The store is auto-created and bootstrapped on first use — there is
|
||||
no `init`/`bootstrap` command, and schemas are ordinary `@schema`-typed nodes (`ucas put
|
||||
Binary: `ocas` (from `@ocas/cli`; legacy alias `ocas` is deprecated). Default store:
|
||||
`~/.uncaged/ocas`. The store is auto-created and bootstrapped on first use — there is
|
||||
no `init`/`bootstrap` command, and schemas are ordinary `@schema`-typed nodes (`ocas put
|
||||
@schema file.json`), so there is no `schema` subcommand.
|
||||
|
||||
### Envelope format
|
||||
@@ -102,12 +102,12 @@ output self-describing and pipeable: feed any envelope into `render -p` to rende
|
||||
raw (non-envelope) text.
|
||||
|
||||
```jsonc
|
||||
// ucas has <hash>
|
||||
// ocas has <hash>
|
||||
{ "type": "AYHQD2YA9G667", "value": true }
|
||||
```
|
||||
|
||||
```
|
||||
Usage: ucas [--store <path>] [--json] <command> [args]
|
||||
Usage: ocas [--store <path>] [--json] <command> [args]
|
||||
|
||||
Commands (all emit a { type, value } envelope unless noted):
|
||||
put <type-hash> <file.json> Store node (value = hash) (@output/put)
|
||||
@@ -127,7 +127,7 @@ Commands (all emit a { type, value } envelope unless noted):
|
||||
gc Garbage collection (@output/gc)
|
||||
|
||||
Flags:
|
||||
--store <path> Store directory (default: ~/.uncaged/json-cas)
|
||||
--store <path> Store directory (default: ~/.uncaged/ocas)
|
||||
--json Compact JSON output
|
||||
--pipe, -p Read a { type, value } envelope from stdin for render
|
||||
```
|
||||
@@ -137,13 +137,13 @@ Flags:
|
||||
```bash
|
||||
# Store a node, then render the stored content (the put envelope's hash is
|
||||
# a cas_ref, so render -p dereferences and renders it):
|
||||
ucas put @schema ./schemas/item.json | ucas render -p
|
||||
ocas put @schema ./schemas/item.json | ocas render -p
|
||||
|
||||
# Render garbage-collection stats:
|
||||
ucas gc | ucas render -p
|
||||
ocas gc | ocas render -p
|
||||
|
||||
# List every schema, then consume the envelope's value array with jq:
|
||||
ucas list --type @schema | jq -r '.value[]'
|
||||
ocas list --type @schema | jq -r '.value[]'
|
||||
```
|
||||
|
||||
## Development
|
||||
@@ -161,7 +161,7 @@ bun test # run all package tests
|
||||
Releases use [Changesets](https://github.com/changesets/changesets). From the repo root:
|
||||
|
||||
```bash
|
||||
bun run release # changeset version → build → publish to npm (@uncaged/*)
|
||||
bun run release # changeset version → build → publish to npm (@ocas/*)
|
||||
```
|
||||
|
||||
Individual packages block `prepublishOnly` and expect releases via the workspace `release` script.
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"includes": ["packages/cli-json-cas/**"],
|
||||
"includes": ["packages/cli/**"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"suspicious": { "noConsole": "off" }
|
||||
|
||||
@@ -13,20 +13,20 @@
|
||||
"ulidx": "^2.4.1",
|
||||
},
|
||||
},
|
||||
"packages/cli-json-cas": {
|
||||
"name": "@uncaged/cli-json-cas",
|
||||
"version": "0.5.3",
|
||||
"packages/cli": {
|
||||
"name": "@ocas/cli",
|
||||
"version": "0.6.0",
|
||||
"bin": {
|
||||
"json-cas": "./src/index.ts",
|
||||
"ocas": "src/index.ts",
|
||||
},
|
||||
"dependencies": {
|
||||
"@uncaged/json-cas": "workspace:^",
|
||||
"@uncaged/json-cas-fs": "workspace:^",
|
||||
"@ocas/core": "^0.6.0",
|
||||
"@ocas/fs": "^0.6.0",
|
||||
},
|
||||
},
|
||||
"packages/json-cas": {
|
||||
"name": "@uncaged/json-cas",
|
||||
"version": "0.5.3",
|
||||
"packages/core": {
|
||||
"name": "@ocas/core",
|
||||
"version": "0.6.0",
|
||||
"dependencies": {
|
||||
"ajv": "^8.20.0",
|
||||
"cborg": "^4.2.3",
|
||||
@@ -34,11 +34,11 @@
|
||||
"xxhash-wasm": "^1.1.0",
|
||||
},
|
||||
},
|
||||
"packages/json-cas-fs": {
|
||||
"name": "@uncaged/json-cas-fs",
|
||||
"version": "0.5.3",
|
||||
"packages/fs": {
|
||||
"name": "@ocas/fs",
|
||||
"version": "0.6.0",
|
||||
"dependencies": {
|
||||
"@uncaged/json-cas": "workspace:^",
|
||||
"@ocas/core": "^0.6.0",
|
||||
"cborg": "^4.2.3",
|
||||
},
|
||||
},
|
||||
@@ -114,14 +114,14 @@
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@ocas/cli": ["@ocas/cli@workspace:packages/cli"],
|
||||
|
||||
"@ocas/core": ["@ocas/core@workspace:packages/core"],
|
||||
|
||||
"@ocas/fs": ["@ocas/fs@workspace:packages/fs"],
|
||||
|
||||
"@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="],
|
||||
|
||||
"@uncaged/cli-json-cas": ["@uncaged/cli-json-cas@workspace:packages/cli-json-cas"],
|
||||
|
||||
"@uncaged/json-cas": ["@uncaged/json-cas@workspace:packages/json-cas"],
|
||||
|
||||
"@uncaged/json-cas-fs": ["@uncaged/json-cas-fs@workspace:packages/json-cas-fs"],
|
||||
|
||||
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
||||
|
||||
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ The root README should have these sections in order:
|
||||
3. **Architecture** — dependency layer diagram (text-based)
|
||||
4. **Packages** — table with ALL packages from packages/ directory, columns: Package, Description, Type (cli/lib)
|
||||
5. **Quick Start** — install, build, basic usage
|
||||
6. **CLI Reference** — brief command list, detailed usage in cli-json-cas README
|
||||
6. **CLI Reference** — brief command list, detailed usage in cli README
|
||||
7. **Development** — bun install / build / check / test
|
||||
8. **Publishing** — changeset workflow (bun run release)
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@uncaged/json-cas-workspace",
|
||||
"name": "@ocas/workspace",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
@@ -13,7 +13,7 @@
|
||||
"ulidx": "^2.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc --build packages/json-cas packages/json-cas-fs",
|
||||
"build": "tsc --build packages/core packages/fs",
|
||||
"test": "bun test",
|
||||
"check": "biome check .",
|
||||
"format": "biome format --write .",
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
# @uncaged/cli-json-cas
|
||||
# @ocas/cli
|
||||
|
||||
CLI tool for json-cas stores.
|
||||
CLI tool for ocas stores.
|
||||
|
||||
## Overview
|
||||
|
||||
`@uncaged/cli-json-cas` provides the `json-cas` command (also aliased `ucas`) for managing a filesystem-backed store: node CRUD, integrity checks, reference listing, graph walks, variables, and output templates. It uses `@uncaged/json-cas-fs` for persistence and `@uncaged/json-cas` for core operations.
|
||||
`@ocas/cli` provides the `ocas` command (also aliased `ocas`) for managing a filesystem-backed store: node CRUD, integrity checks, reference listing, graph walks, variables, and output templates. It uses `@ocas/fs` for persistence and `@ocas/core` for core operations.
|
||||
|
||||
The store is **auto-created and bootstrapped** on first use, so there is no `init`/`bootstrap` command. Schemas are ordinary `@schema`-typed nodes — register one with `ucas put @schema file.json` and list them with `ucas list --type @schema`; there is no dedicated `schema` subcommand.
|
||||
The store is **auto-created and bootstrapped** on first use, so there is no `init`/`bootstrap` command. Schemas are ordinary `@schema`-typed nodes — register one with `ocas put @schema file.json` and list them with `ocas list --type @schema`; there is no dedicated `schema` subcommand.
|
||||
|
||||
**Dependencies:** `@uncaged/json-cas`, `@uncaged/json-cas-fs`
|
||||
**Dependencies:** `@ocas/core`, `@ocas/fs`
|
||||
|
||||
## Installation
|
||||
|
||||
Published as an npm package with a binary entry:
|
||||
|
||||
```bash
|
||||
bun add -g @uncaged/cli-json-cas
|
||||
bun add -g @ocas/cli
|
||||
# or from the monorepo workspace:
|
||||
bun link
|
||||
```
|
||||
|
||||
**Binary name:** `json-cas` (points to `src/index.ts`, run with Bun).
|
||||
**Binary name:** `ocas` (points to `src/index.ts`, run with Bun).
|
||||
|
||||
In development:
|
||||
|
||||
```bash
|
||||
bun packages/cli-json-cas/src/index.ts <command> [args]
|
||||
bun packages/cli-ocas/src/index.ts <command> [args]
|
||||
```
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```
|
||||
Usage: json-cas [--store <path>] [--json] <command> [args]
|
||||
Usage: ocas [--store <path>] [--json] <command> [args]
|
||||
```
|
||||
|
||||
### Global flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--store <path>` | Store directory (default: `~/.uncaged/json-cas`) |
|
||||
| `--store <path>` | Store directory (default: `~/.uncaged/ocas`) |
|
||||
| `--var-db <path>` | Variable database path (default: `<store>/variables.db`) |
|
||||
| `--json` | Compact (single-line) JSON output |
|
||||
|
||||
@@ -51,10 +51,10 @@ is therefore self-describing and pipeable: feed any envelope into `render -p` to
|
||||
raw, non-envelope text.
|
||||
|
||||
```jsonc
|
||||
// json-cas has <hash>
|
||||
// ocas has <hash>
|
||||
{ "type": "AYHQD2YA9G667", "value": true }
|
||||
|
||||
// json-cas template set <schema-hash> --inline "Hi {{ payload.name }}"
|
||||
// ocas template set <schema-hash> --inline "Hi {{ payload.name }}"
|
||||
{ "type": "9YJZ09DDAYAWR", "value": { "schemaHash": "7XX5H51CVD9H0", "contentHash": "FC8WACA792B6F" } }
|
||||
```
|
||||
|
||||
@@ -87,18 +87,18 @@ raw, non-envelope text.
|
||||
|
||||
```bash
|
||||
# Register a schema (schemas are plain @schema nodes) and store a payload
|
||||
json-cas put @schema ./schemas/item.json
|
||||
ocas put @schema ./schemas/item.json
|
||||
# → { "type": "...", "value": "0123456789ABC" } (the schema's type hash)
|
||||
|
||||
json-cas put 0123456789ABC ./payloads/item.json
|
||||
ocas put 0123456789ABC ./payloads/item.json
|
||||
# → { "type": "...", "value": "<content-hash>" }
|
||||
|
||||
json-cas get <content-hash> --json
|
||||
json-cas verify <content-hash>
|
||||
json-cas walk <content-hash> --format tree
|
||||
ocas get <content-hash> --json
|
||||
ocas verify <content-hash>
|
||||
ocas walk <content-hash> --format tree
|
||||
|
||||
# List every registered schema, then extract the hashes with jq
|
||||
json-cas list --type @schema | jq -r '.value[]'
|
||||
ocas list --type @schema | jq -r '.value[]'
|
||||
```
|
||||
|
||||
### Pipe composition
|
||||
@@ -108,25 +108,25 @@ Because every command shares the `{ type, value }` envelope, output composes dir
|
||||
|
||||
```bash
|
||||
# put emits a cas_ref hash envelope; render -p dereferences and renders the node
|
||||
json-cas put @schema ./schemas/item.json | json-cas render -p
|
||||
ocas put @schema ./schemas/item.json | ocas render -p
|
||||
|
||||
# render gc statistics
|
||||
json-cas gc | json-cas render -p
|
||||
ocas gc | ocas render -p
|
||||
|
||||
# render every schema referenced by a list result
|
||||
json-cas list --type @schema | json-cas render -p
|
||||
ocas list --type @schema | ocas render -p
|
||||
```
|
||||
|
||||
### Templates
|
||||
|
||||
`template` commands manage the LiquidJS template bound to a schema (stored as a
|
||||
`@ucas/template/text/<schema-hash>` variable). `render <hash>` uses the template registered
|
||||
`@ocas/template/text/<schema-hash>` variable). `render <hash>` uses the template registered
|
||||
for the node's type, falling back to YAML when none exists.
|
||||
|
||||
```bash
|
||||
# Bind a template to a schema, then render a node of that type
|
||||
json-cas template set 0123456789ABC --inline "Item: {{ payload.name }}"
|
||||
json-cas render <content-hash>
|
||||
ocas template set 0123456789ABC --inline "Item: {{ payload.name }}"
|
||||
ocas render <content-hash>
|
||||
# → Item: Widget
|
||||
```
|
||||
|
||||
@@ -142,6 +142,6 @@ There is no separate `src/` module tree; the CLI is a single entry file. Tests (
|
||||
|
||||
| Setting | Default | Override |
|
||||
|---------|---------|----------|
|
||||
| Store directory | `~/.uncaged/json-cas` | `--store <path>` |
|
||||
| Store directory | `~/.uncaged/ocas` | `--store <path>` |
|
||||
|
||||
No config file is read; all behavior is controlled via flags and command arguments.
|
||||
@@ -1,17 +1,16 @@
|
||||
{
|
||||
"name": "@uncaged/cli-json-cas",
|
||||
"name": "@ocas/cli",
|
||||
"version": "0.6.0",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"json-cas": "./src/index.ts",
|
||||
"ucas": "./src/index.ts"
|
||||
"ocas": "src/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "bun test",
|
||||
"prepublishOnly": "bash ../../scripts/check-workspace-deps.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uncaged/json-cas": "^0.6.0",
|
||||
"@uncaged/json-cas-fs": "^0.6.0"
|
||||
"@ocas/core": "^0.6.0",
|
||||
"@ocas/fs": "^0.6.0"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import type { Hash, Store, VariableStore } from "@uncaged/json-cas";
|
||||
import type { Hash, Store, VariableStore } from "@ocas/core";
|
||||
import {
|
||||
bootstrap,
|
||||
CasNodeNotFoundError,
|
||||
@@ -23,8 +23,8 @@ import {
|
||||
verify,
|
||||
walk,
|
||||
wrapEnvelope,
|
||||
} from "@uncaged/json-cas";
|
||||
import { openStore as openFsStore } from "@uncaged/json-cas-fs";
|
||||
} from "@ocas/core";
|
||||
import { openStore as openFsStore } from "@ocas/fs";
|
||||
|
||||
// ---- Argument parsing ----
|
||||
|
||||
@@ -87,7 +87,7 @@ function parseArgs(argv: string[]): { flags: Flags; positional: string[] } {
|
||||
|
||||
const { flags, positional } = parseArgs(process.argv.slice(2));
|
||||
|
||||
const defaultStorePath = join(homedir(), ".uncaged", "json-cas");
|
||||
const defaultStorePath = join(homedir(), ".ocas");
|
||||
const storePath =
|
||||
typeof flags.store === "string" ? flags.store : defaultStorePath;
|
||||
const compact = flags.json === true;
|
||||
@@ -203,7 +203,7 @@ async function cmdPut(args: string[]): Promise<void> {
|
||||
const file = isPipe ? undefined : args[1];
|
||||
if (!typeHashOrAlias || (!isPipe && !file))
|
||||
die(
|
||||
"Usage: json-cas put <type-hash> <file.json>\n json-cas put <type-hash> --pipe/-p",
|
||||
"Usage: ocas put <type-hash> <file.json>\n ocas put <type-hash> --pipe/-p",
|
||||
);
|
||||
if (isPipe && args[1])
|
||||
die("Cannot use --pipe/-p with a file argument. Use one or the other.");
|
||||
@@ -250,7 +250,7 @@ async function cmdPut(args: string[]): Promise<void> {
|
||||
|
||||
async function cmdGet(args: string[]): Promise<void> {
|
||||
const hash = args[0];
|
||||
if (!hash) die("Usage: json-cas get <hash>");
|
||||
if (!hash) die("Usage: ocas get <hash>");
|
||||
const store = await openStore();
|
||||
const node = store.get(hash);
|
||||
if (node === null) die(`Node not found: ${hash}`);
|
||||
@@ -259,14 +259,14 @@ async function cmdGet(args: string[]): Promise<void> {
|
||||
|
||||
async function cmdHas(args: string[]): Promise<void> {
|
||||
const hash = args[0];
|
||||
if (!hash) die("Usage: json-cas has <hash>");
|
||||
if (!hash) die("Usage: ocas has <hash>");
|
||||
const store = await openStore();
|
||||
out(await wrapEnvelope(store, "@output/has", store.has(hash)));
|
||||
}
|
||||
|
||||
async function cmdVerify(args: string[]): Promise<void> {
|
||||
const hash = args[0];
|
||||
if (!hash) die("Usage: json-cas verify <hash>");
|
||||
if (!hash) die("Usage: ocas verify <hash>");
|
||||
const store = await openStore();
|
||||
const node = store.get(hash);
|
||||
if (node === null) die(`Node not found: ${hash}`);
|
||||
@@ -282,7 +282,7 @@ async function cmdVerify(args: string[]): Promise<void> {
|
||||
|
||||
async function cmdRefs(args: string[]): Promise<void> {
|
||||
const hash = args[0];
|
||||
if (!hash) die("Usage: json-cas refs <hash>");
|
||||
if (!hash) die("Usage: ocas refs <hash>");
|
||||
const store = await openStore();
|
||||
const node = store.get(hash);
|
||||
if (node === null) die(`Node not found: ${hash}`);
|
||||
@@ -292,7 +292,7 @@ async function cmdRefs(args: string[]): Promise<void> {
|
||||
|
||||
async function cmdWalk(args: string[]): Promise<void> {
|
||||
const hash = args[0];
|
||||
if (!hash) die("Usage: json-cas walk <hash> [--format tree]");
|
||||
if (!hash) die("Usage: ocas walk <hash> [--format tree]");
|
||||
const store = await openStore();
|
||||
const format = flags.format;
|
||||
|
||||
@@ -339,7 +339,7 @@ async function cmdHash(args: string[]): Promise<void> {
|
||||
const file = isPipe ? undefined : args[1];
|
||||
if (!typeHashOrAlias || (!isPipe && !file))
|
||||
die(
|
||||
"Usage: json-cas hash <type-hash> <file.json>\n json-cas hash <type-hash> --pipe/-p",
|
||||
"Usage: ocas hash <type-hash> <file.json>\n ocas hash <type-hash> --pipe/-p",
|
||||
);
|
||||
if (isPipe && args[1])
|
||||
die("Cannot use --pipe/-p with a file argument. Use one or the other.");
|
||||
@@ -360,7 +360,7 @@ async function cmdRender(args: string[]): Promise<void> {
|
||||
|
||||
if (!isPipe && !hash) {
|
||||
die(
|
||||
"Usage: ucas render <hash> [--resolution <n>] [--decay <n>] [--epsilon <n>]\n ucas render --pipe/-p [--resolution <n>] [--decay <n>] [--epsilon <n>]",
|
||||
"Usage: ocas render <hash> [--resolution <n>] [--decay <n>] [--epsilon <n>]\n ocas render --pipe/-p [--resolution <n>] [--decay <n>] [--epsilon <n>]",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ async function cmdVarSet(args: string[]): Promise<void> {
|
||||
const tagFlags = flags.tag;
|
||||
|
||||
if (!name || !value) {
|
||||
die("Usage: json-cas var set <name> <hash> [--tag <tag>...]");
|
||||
die("Usage: ocas var set <name> <hash> [--tag <tag>...]");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
@@ -517,7 +517,7 @@ async function cmdVarGet(args: string[]): Promise<void> {
|
||||
const schema = flags.schema as string | undefined;
|
||||
|
||||
if (!name || !schema) {
|
||||
die("Usage: json-cas var get <name> --schema <hash>");
|
||||
die("Usage: ocas var get <name> --schema <hash>");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
@@ -539,7 +539,7 @@ async function cmdVarDelete(args: string[]): Promise<void> {
|
||||
const schema = flags.schema as string | undefined;
|
||||
|
||||
if (!name) {
|
||||
die("Usage: json-cas var delete <name> [--schema <hash>]");
|
||||
die("Usage: ocas var delete <name> [--schema <hash>]");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
@@ -570,12 +570,12 @@ async function cmdVarTag(args: string[]): Promise<void> {
|
||||
const schema = flags.schema as string | undefined;
|
||||
|
||||
if (!name || !schema) {
|
||||
die("Usage: json-cas var tag <name> --schema <hash> <operations...>");
|
||||
die("Usage: ocas var tag <name> --schema <hash> <operations...>");
|
||||
}
|
||||
|
||||
const tagArgs = args.slice(1);
|
||||
if (tagArgs.length === 0) {
|
||||
die("Usage: json-cas var tag <name> --schema <hash> <operations...>");
|
||||
die("Usage: ocas var tag <name> --schema <hash> <operations...>");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
@@ -649,7 +649,7 @@ async function cmdTemplateSet(args: string[]): Promise<void> {
|
||||
const inlineFlag = flags.inline;
|
||||
|
||||
if (!schemaHash) {
|
||||
die("Usage: json-cas template set <schema-hash> <file> | --inline <text>");
|
||||
die("Usage: ocas template set <schema-hash> <file> | --inline <text>");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
@@ -675,18 +675,14 @@ async function cmdTemplateSet(args: string[]): Promise<void> {
|
||||
// --inline flag present but no value
|
||||
const contentArg = args[1];
|
||||
if (!contentArg) {
|
||||
die(
|
||||
"Usage: json-cas template set <schema-hash> <file> | --inline <text>",
|
||||
);
|
||||
die("Usage: ocas template set <schema-hash> <file> | --inline <text>");
|
||||
}
|
||||
content = contentArg;
|
||||
} else {
|
||||
// File mode
|
||||
const file = args[1];
|
||||
if (!file) {
|
||||
die(
|
||||
"Usage: json-cas template set <schema-hash> <file> | --inline <text>",
|
||||
);
|
||||
die("Usage: ocas template set <schema-hash> <file> | --inline <text>");
|
||||
}
|
||||
if (!existsSync(file)) {
|
||||
die(`Error: File not found: ${file}`);
|
||||
@@ -698,8 +694,8 @@ async function cmdTemplateSet(args: string[]): Promise<void> {
|
||||
const stringHash = await resolveTypeHash("@string");
|
||||
const contentHash = await store.put(stringHash, content);
|
||||
|
||||
// Create variable binding: @ucas/template/text/<schema-hash>
|
||||
const varName = `@ucas/template/text/${schemaHash}`;
|
||||
// Create variable binding: @ocas/template/text/<schema-hash>
|
||||
const varName = `@ocas/template/text/${schemaHash}`;
|
||||
varStore.set(varName, contentHash);
|
||||
|
||||
out(
|
||||
@@ -722,14 +718,14 @@ async function cmdTemplateGet(args: string[]): Promise<void> {
|
||||
const schemaHash = args[0];
|
||||
|
||||
if (!schemaHash) {
|
||||
die("Usage: json-cas template get <schema-hash>");
|
||||
die("Usage: ocas template get <schema-hash>");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
const varStore = createVariableStore(resolve(varDbPath), store);
|
||||
|
||||
try {
|
||||
const varName = `@ucas/template/text/${schemaHash}`;
|
||||
const varName = `@ocas/template/text/${schemaHash}`;
|
||||
const stringHash = await resolveTypeHash("@string");
|
||||
const variable = varStore.get(varName, stringHash);
|
||||
|
||||
@@ -758,12 +754,12 @@ async function cmdTemplateList(_args: string[]): Promise<void> {
|
||||
try {
|
||||
const stringHash = await resolveTypeHash("@string");
|
||||
const variables = varStore.list({
|
||||
namePrefix: "@ucas/template/text/",
|
||||
namePrefix: "@ocas/template/text/",
|
||||
schema: stringHash,
|
||||
});
|
||||
|
||||
const templates = variables.map((v) => ({
|
||||
schemaHash: v.name.replace("@ucas/template/text/", ""),
|
||||
schemaHash: v.name.replace("@ocas/template/text/", ""),
|
||||
contentHash: v.value,
|
||||
}));
|
||||
|
||||
@@ -777,14 +773,14 @@ async function cmdTemplateDelete(args: string[]): Promise<void> {
|
||||
const schemaHash = args[0];
|
||||
|
||||
if (!schemaHash) {
|
||||
die("Usage: json-cas template delete <schema-hash>");
|
||||
die("Usage: ocas template delete <schema-hash>");
|
||||
}
|
||||
|
||||
const store = await openStore();
|
||||
const varStore = createVariableStore(resolve(varDbPath), store);
|
||||
|
||||
try {
|
||||
const varName = `@ucas/template/text/${schemaHash}`;
|
||||
const varName = `@ocas/template/text/${schemaHash}`;
|
||||
const stringHash = await resolveTypeHash("@string");
|
||||
varStore.remove(varName, stringHash);
|
||||
|
||||
@@ -816,7 +812,7 @@ async function cmdGc(_args: string[]): Promise<void> {
|
||||
async function cmdList(_args: string[]): Promise<void> {
|
||||
const typeFlag = flags.type;
|
||||
if (typeof typeFlag !== "string")
|
||||
die("Usage: json-cas list --type <hash-or-alias>");
|
||||
die("Usage: ocas list --type <hash-or-alias>");
|
||||
const typeHash = await resolveTypeHash(typeFlag);
|
||||
const store = await openStore();
|
||||
const hashes = Array.from(store.listByType(typeHash));
|
||||
@@ -837,7 +833,7 @@ async function cmdListSchema(_args: string[]): Promise<void> {
|
||||
|
||||
function printUsage(): void {
|
||||
console.log(`\
|
||||
Usage: json-cas [--store <path>] [--json] <command> [args]
|
||||
Usage: ocas [--store <path>] [--json] <command> [args]
|
||||
|
||||
All JSON commands emit a { type, value } envelope. The type is the hash of the
|
||||
command's @output/* schema (shown in parentheses); pipe any envelope into
|
||||
@@ -868,7 +864,7 @@ Commands:
|
||||
gc Run garbage collection (@output/gc)
|
||||
|
||||
Flags:
|
||||
--store <path> Store directory (default: ~/.uncaged/json-cas)
|
||||
--store <path> Store directory (default: ~/.ocas)
|
||||
--var-db <path> Variable database path (default: <store>/variables.db)
|
||||
--json Compact JSON output
|
||||
--schema <hash> Schema hash filter for var get/delete/tag/list
|
||||
+43
-43
@@ -2,12 +2,12 @@
|
||||
|
||||
exports[`Phase 7: Edge Cases 7.1 get non-existent hash errors gracefully 1`] = `"Node not found: AAAAAAAAAAAAA"`;
|
||||
|
||||
exports[`Phase 7: Edge Cases 7.3 var set empty name errors 1`] = `"Usage: json-cas var set <name> <hash> [--tag <tag>...]"`;
|
||||
exports[`Phase 7: Edge Cases 7.3 var set empty name errors 1`] = `"Usage: ocas var set <name> <hash> [--tag <tag>...]"`;
|
||||
|
||||
exports[`Phase 7: Edge Cases 7.4 var set name with invalid chars errors 1`] = `"Error: Invalid variable name "invalid name!": Segment "invalid name!" contains invalid characters (only @, a-z, A-Z, 0-9, ., _, - allowed)"`;
|
||||
|
||||
exports[`Phase 7: Edge Cases 7.5 no subcommand shows help text 1`] = `
|
||||
"Usage: json-cas [--store <path>] [--json] <command> [args]
|
||||
"Usage: ocas [--store <path>] [--json] <command> [args]
|
||||
|
||||
All JSON commands emit a { type, value } envelope. The type is the hash of the
|
||||
command's @output/* schema (shown in parentheses); pipe any envelope into
|
||||
@@ -38,7 +38,7 @@ Commands:
|
||||
gc Run garbage collection (@output/gc)
|
||||
|
||||
Flags:
|
||||
--store <path> Store directory (default: ~/.uncaged/json-cas)
|
||||
--store <path> Store directory (default: ~/.ocas)
|
||||
--var-db <path> Variable database path (default: <store>/variables.db)
|
||||
--json Compact JSON output
|
||||
--schema <hash> Schema hash filter for var get/delete/tag/list
|
||||
@@ -52,40 +52,40 @@ Flags:
|
||||
|
||||
exports[`Phase 3: Variable System 3.1 var set creates variable 1`] = `
|
||||
{
|
||||
"type": "5KVHSESSX7N96",
|
||||
"type": "50CG6QYD1FY8J",
|
||||
"value": {
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.2 var get returns variable 1`] = `
|
||||
{
|
||||
"type": "7D4R2MJ1EYF08",
|
||||
"type": "DSXYC9DNCYAK0",
|
||||
"value": {
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.3 var list shows all variables 1`] = `
|
||||
{
|
||||
"type": "E8158M25YNR9M",
|
||||
"type": "8F5ENFRC57Y7H",
|
||||
"value": [
|
||||
{
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -93,14 +93,14 @@ exports[`Phase 3: Variable System 3.3 var list shows all variables 1`] = `
|
||||
|
||||
exports[`Phase 3: Variable System 3.4 var list prefix filters by prefix 1`] = `
|
||||
{
|
||||
"type": "E8158M25YNR9M",
|
||||
"type": "8F5ENFRC57Y7H",
|
||||
"value": [
|
||||
{
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -108,48 +108,48 @@ exports[`Phase 3: Variable System 3.4 var list prefix filters by prefix 1`] = `
|
||||
|
||||
exports[`Phase 3: Variable System 3.5 var set upsert updates existing variable 1`] = `
|
||||
{
|
||||
"type": "5KVHSESSX7N96",
|
||||
"type": "50CG6QYD1FY8J",
|
||||
"value": {
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {},
|
||||
"value": "AE80669JYG4K2",
|
||||
"value": "A6QPKJAFR68NP",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.6 var tag adds kv tag and label 1`] = `
|
||||
{
|
||||
"type": "2WX4XRYSACRWR",
|
||||
"type": "6D1HG60NTZY87",
|
||||
"value": {
|
||||
"labels": [
|
||||
"important",
|
||||
],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {
|
||||
"env": "prod",
|
||||
},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.7 var list --tag env:prod filters by kv tag 1`] = `
|
||||
{
|
||||
"type": "E8158M25YNR9M",
|
||||
"type": "8F5ENFRC57Y7H",
|
||||
"value": [
|
||||
{
|
||||
"labels": [
|
||||
"important",
|
||||
],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {
|
||||
"env": "prod",
|
||||
},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -157,18 +157,18 @@ exports[`Phase 3: Variable System 3.7 var list --tag env:prod filters by kv tag
|
||||
|
||||
exports[`Phase 3: Variable System 3.8 var list --tag important filters by label 1`] = `
|
||||
{
|
||||
"type": "E8158M25YNR9M",
|
||||
"type": "8F5ENFRC57Y7H",
|
||||
"value": [
|
||||
{
|
||||
"labels": [
|
||||
"important",
|
||||
],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {
|
||||
"env": "prod",
|
||||
},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -176,62 +176,62 @@ exports[`Phase 3: Variable System 3.8 var list --tag important filters by label
|
||||
|
||||
exports[`Phase 3: Variable System 3.9 var tag remove deletes label 1`] = `
|
||||
{
|
||||
"type": "2WX4XRYSACRWR",
|
||||
"type": "6D1HG60NTZY87",
|
||||
"value": {
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {
|
||||
"env": "prod",
|
||||
},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.10 var delete removes variable 1`] = `
|
||||
{
|
||||
"type": "F89626QEK09YY",
|
||||
"type": "25VAMSJT0X51K",
|
||||
"value": [
|
||||
{
|
||||
"labels": [],
|
||||
"name": "myapp/config",
|
||||
"schema": "8WAZV39SD724T",
|
||||
"schema": "FRBAB1BF0ZBCS",
|
||||
"tags": {
|
||||
"env": "prod",
|
||||
},
|
||||
"value": "6KZ930XYK2MHB",
|
||||
"value": "9W3MGR3184QYE",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 3: Variable System 3.11 var get deleted variable returns not found 1`] = `"Error: Variable not found: name=myapp/config, schema=8WAZV39SD724T"`;
|
||||
exports[`Phase 3: Variable System 3.11 var get deleted variable returns not found 1`] = `"Error: Variable not found: name=myapp/config, schema=FRBAB1BF0ZBCS"`;
|
||||
|
||||
exports[`Phase 4: Template System 4.1 template set registers template 1`] = `
|
||||
{
|
||||
"type": "A8RGY9B1JSCDJ",
|
||||
"type": "7R13JNSN53R67",
|
||||
"value": {
|
||||
"contentHash": "0359SHMP7VBFD",
|
||||
"schemaHash": "8WAZV39SD724T",
|
||||
"contentHash": "6WW8WNB38GTTP",
|
||||
"schemaHash": "FRBAB1BF0ZBCS",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 4: Template System 4.2 template get returns template text 1`] = `
|
||||
{
|
||||
"type": "64FP3TWKK69YH",
|
||||
"type": "0B0HBHZGYHR84",
|
||||
"value": "Name: {{ payload.name }}, Age: {{ payload.age }}",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 4: Template System 4.3 template list shows registered templates 1`] = `
|
||||
{
|
||||
"type": "BE20H482GBNM3",
|
||||
"type": "5GE3Y0EQS0HP4",
|
||||
"value": [
|
||||
{
|
||||
"contentHash": "0359SHMP7VBFD",
|
||||
"schemaHash": "8WAZV39SD724T",
|
||||
"contentHash": "6WW8WNB38GTTP",
|
||||
"schemaHash": "FRBAB1BF0ZBCS",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -239,11 +239,11 @@ exports[`Phase 4: Template System 4.3 template list shows registered templates 1
|
||||
|
||||
exports[`Phase 4: Template System 4.4 template delete removes template 1`] = `
|
||||
{
|
||||
"type": "0FXB2GS8Y9R1R",
|
||||
"type": "BY7BGZJND3N7R",
|
||||
"value": {
|
||||
"deleted": true,
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 4: Template System 4.5 template get deleted template returns not found 1`] = `"Error: Template not found for schema: 8WAZV39SD724T"`;
|
||||
exports[`Phase 4: Template System 4.5 template get deleted template returns not found 1`] = `"Error: Template not found for schema: FRBAB1BF0ZBCS"`;
|
||||
+2
-2
@@ -2,13 +2,13 @@
|
||||
|
||||
exports[`Phase 1: CAS Core 1.6 get returns node JSON (snapshot) 1`] = `
|
||||
{
|
||||
"type": "CE40D09H75NFZ",
|
||||
"type": "CCVN1ECY8JKQ0",
|
||||
"value": {
|
||||
"payload": {
|
||||
"age": 30,
|
||||
"name": "Alice",
|
||||
},
|
||||
"type": "8WAZV39SD724T",
|
||||
"type": "FRBAB1BF0ZBCS",
|
||||
},
|
||||
}
|
||||
`;
|
||||
+4
-4
@@ -2,23 +2,23 @@
|
||||
|
||||
exports[`Phase 1: CAS Core 1.9 verify returns ok for valid node 1`] = `
|
||||
{
|
||||
"type": "BZ31JDDWX2AWH",
|
||||
"type": "52HEFB52BD0GF",
|
||||
"value": "ok",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Phase 1: CAS Core 1.10 refs lists direct references (snapshot) 1`] = `
|
||||
"{
|
||||
"type": "DG8SAB75PV9P7",
|
||||
"type": "35QJB2WESFFGQ",
|
||||
"value": []
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`Phase 1: CAS Core 1.11 walk shows traversal tree (snapshot) 1`] = `
|
||||
"{
|
||||
"type": "EVHG7Q7FK83H0",
|
||||
"type": "4HG6MD3XG5H5C",
|
||||
"value": [
|
||||
"6KZ930XYK2MHB"
|
||||
"9W3MGR3184QYE"
|
||||
]
|
||||
}"
|
||||
`;
|
||||
@@ -13,7 +13,7 @@ beforeEach(() => {
|
||||
// Create unique temp directory for each test
|
||||
testDir = join(
|
||||
tmpdir(),
|
||||
`json-cas-cli-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
`ocas-cli-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
);
|
||||
storePath = join(testDir, "store");
|
||||
cliPath = join(import.meta.dir, "../src/index.ts");
|
||||
@@ -67,7 +67,7 @@ function envValue(json: string): unknown {
|
||||
}
|
||||
|
||||
describe("@ Alias Resolution - put", () => {
|
||||
test("ucas put @string <file> should resolve alias", async () => {
|
||||
test("ocas put @string <file> should resolve alias", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
@@ -85,7 +85,7 @@ describe("@ Alias Resolution - put", () => {
|
||||
expect(envValue(stdout)).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("ucas put @number <file> should resolve alias", async () => {
|
||||
test("ocas put @number <file> should resolve alias", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
@@ -101,7 +101,7 @@ describe("@ Alias Resolution - put", () => {
|
||||
expect(envValue(stdout)).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("ucas put @object <file> should resolve alias", async () => {
|
||||
test("ocas put @object <file> should resolve alias", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
@@ -117,7 +117,7 @@ describe("@ Alias Resolution - put", () => {
|
||||
expect(envValue(stdout)).toMatch(/^[0-9A-HJKMNP-TV-Z]{13}$/);
|
||||
});
|
||||
|
||||
test("ucas put @invalid <file> should fail", async () => {
|
||||
test("ocas put @invalid <file> should fail", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
@@ -133,7 +133,7 @@ describe("@ Alias Resolution - put", () => {
|
||||
expect(stderr.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("ucas put @schema with nested type constraints should succeed", async () => {
|
||||
test("ocas put @schema with nested type constraints should succeed", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const schemaFile = join(testDir, "constrained-schema.json");
|
||||
@@ -168,7 +168,7 @@ describe("@ Alias Resolution - put", () => {
|
||||
});
|
||||
|
||||
describe("@ Alias Resolution - hash", () => {
|
||||
test("ucas hash @string <file> should compute hash without storing", async () => {
|
||||
test("ocas hash @string <file> should compute hash without storing", async () => {
|
||||
await runCliAlias("init");
|
||||
|
||||
const payloadFile = join(testDir, "payload.json");
|
||||
+18
-21
@@ -7,20 +7,22 @@ import { envValue, stripVolatile } from "./helpers";
|
||||
const entrypoint = resolve(import.meta.dir, "../src/index.ts");
|
||||
const pkgPath = resolve(import.meta.dir, "../package.json");
|
||||
|
||||
// --- ucas command alias tests (from cli.test.ts) ---
|
||||
// --- ocas command alias tests (from cli.test.ts) ---
|
||||
|
||||
describe("ucas command alias", () => {
|
||||
test("T1: ucas bin entry exists in package.json", async () => {
|
||||
describe("ocas binary", () => {
|
||||
test("T1: ocas bin entry exists in package.json", async () => {
|
||||
const pkg = await Bun.file(pkgPath).json();
|
||||
expect(pkg.bin.ucas).toBe("./src/index.ts");
|
||||
expect(pkg.bin.ocas).toBe("src/index.ts");
|
||||
});
|
||||
|
||||
test("T2: json-cas bin entry is preserved in package.json", async () => {
|
||||
test("T2: no legacy bin entries (json-cas, ucas)", async () => {
|
||||
const pkg = await Bun.file(pkgPath).json();
|
||||
expect(pkg.bin["json-cas"]).toBe("./src/index.ts");
|
||||
expect(pkg.bin["json-cas"]).toBeUndefined();
|
||||
expect(pkg.bin["ucas"]).toBeUndefined();
|
||||
expect(Object.keys(pkg.bin)).toEqual(["ocas"]);
|
||||
});
|
||||
|
||||
test("T3: ucas command is executable and shows help", async () => {
|
||||
test("T3: ocas command is executable and shows help", async () => {
|
||||
const proc = Bun.spawn(["bun", entrypoint, "--help"], {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
@@ -30,11 +32,6 @@ describe("ucas command alias", () => {
|
||||
expect(exitCode).toBe(0);
|
||||
expect(stdout.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("T4: both commands point to the same entrypoint", async () => {
|
||||
const pkg = await Bun.file(pkgPath).json();
|
||||
expect(pkg.bin.ucas).toBe(pkg.bin["json-cas"]);
|
||||
});
|
||||
});
|
||||
|
||||
// --- e2e Phase 7: Edge Cases ---
|
||||
@@ -59,7 +56,7 @@ describe("Phase 7: Edge Cases", () => {
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -72,8 +69,8 @@ describe("Phase 7: Edge Cases", () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -178,7 +175,7 @@ describe("Phase 3: Variable System", () => {
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -191,8 +188,8 @@ describe("Phase 3: Variable System", () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -367,7 +364,7 @@ describe("Phase 4: Template System", () => {
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -380,8 +377,8 @@ describe("Phase 4: Template System", () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -12,7 +12,7 @@ let typeHash: string;
|
||||
let nodeHash: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -25,8 +25,8 @@ beforeAll(async () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import type { JSONSchema } from "@uncaged/json-cas";
|
||||
import { putSchema } from "@uncaged/json-cas";
|
||||
import { openStore as openFsStore } from "@uncaged/json-cas-fs";
|
||||
import type { JSONSchema } from "@ocas/core";
|
||||
import { putSchema } from "@ocas/core";
|
||||
import { openStore as openFsStore } from "@ocas/fs";
|
||||
|
||||
export {
|
||||
join,
|
||||
+5
-5
@@ -2,14 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
||||
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { BOOTSTRAP_STORE } from "@uncaged/json-cas";
|
||||
import { openStore as openFsStore } from "@uncaged/json-cas-fs";
|
||||
import { BOOTSTRAP_STORE } from "@ocas/core";
|
||||
import { openStore as openFsStore } from "@ocas/fs";
|
||||
import { envValue, runCli } from "./helpers.js";
|
||||
|
||||
let storePath: string;
|
||||
|
||||
beforeEach(() => {
|
||||
storePath = mkdtempSync(join(tmpdir(), "json-cas-list-meta-schema-"));
|
||||
storePath = mkdtempSync(join(tmpdir(), "ocas-list-meta-schema-"));
|
||||
mkdirSync(storePath, { recursive: true });
|
||||
});
|
||||
|
||||
@@ -98,7 +98,7 @@ describe("F1. output schemas registered", () => {
|
||||
const node = envValue(getOut) as {
|
||||
payload: { title?: string };
|
||||
};
|
||||
expect(node.payload.title).toBe("ucas list-meta result");
|
||||
expect(node.payload.title).toBe("ocas list-meta result");
|
||||
|
||||
const { stdout: schemaOut } = await runCli(["list-schema"], storePath);
|
||||
const schemaParsed = JSON.parse(schemaOut) as { type: string };
|
||||
@@ -110,7 +110,7 @@ describe("F1. output schemas registered", () => {
|
||||
const schNode = envValue(getSchOut) as {
|
||||
payload: { title?: string };
|
||||
};
|
||||
expect(schNode.payload.title).toBe("ucas list-schema result");
|
||||
expect(schNode.payload.title).toBe("ocas list-schema result");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@ let typeHash: string;
|
||||
let nodeHash: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -25,8 +25,8 @@ beforeAll(async () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
+3
-3
@@ -12,7 +12,7 @@ let typeHash: string;
|
||||
let nodeHash: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -28,8 +28,8 @@ beforeAll(async () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -2,15 +2,15 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { bootstrap } from "@uncaged/json-cas";
|
||||
import { createFsStore } from "@uncaged/json-cas-fs";
|
||||
import { bootstrap } from "@ocas/core";
|
||||
import { createFsStore } from "@ocas/fs";
|
||||
import { envValue, putSchemaFile, runCli, runCliWithStdin } from "./helpers";
|
||||
|
||||
const entrypoint = resolve(import.meta.dir, "../src/index.ts");
|
||||
|
||||
// --- Standalone render tests from cli.test.ts ---
|
||||
|
||||
describe("ucas render command", () => {
|
||||
describe("ocas render command", () => {
|
||||
test("R1: render requires hash argument", async () => {
|
||||
const { exitCode, stderr } = await runCli(["render"]);
|
||||
expect(exitCode).not.toBe(0);
|
||||
@@ -18,7 +18,7 @@ describe("ucas render command", () => {
|
||||
});
|
||||
|
||||
test("R2: render with missing hash shows error", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
const { exitCode, stderr } = await runCli(
|
||||
@@ -35,7 +35,7 @@ describe("ucas render command", () => {
|
||||
});
|
||||
|
||||
test("R3: render with invalid numeric flag fails", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
const { exitCode, stderr } = await runCli(
|
||||
@@ -88,7 +88,7 @@ describe("Phase 5: Render", () => {
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -101,8 +101,8 @@ describe("Phase 5: Render", () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -154,7 +154,7 @@ describe("Phase 5: Render", () => {
|
||||
|
||||
describe("Suite 6: CLI Integration with Templates", () => {
|
||||
test("6.1 CLI with Template (Default Parameters)", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
// Initialize store
|
||||
await runCli(["init"], tmpStore);
|
||||
@@ -190,7 +190,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
|
||||
// Register template
|
||||
await runCli(
|
||||
["var", "set", `@ucas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
["var", "set", `@ocas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
tmpStore,
|
||||
);
|
||||
|
||||
@@ -208,7 +208,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("6.2 CLI with Template + Custom Decay", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -263,7 +263,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
|
||||
// Register template
|
||||
await runCli(
|
||||
["var", "set", `@ucas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
["var", "set", `@ocas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
tmpStore,
|
||||
);
|
||||
|
||||
@@ -281,7 +281,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("6.3 CLI with Template + All Parameters", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -316,7 +316,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
const tmplHash = envValue(tmplOut) as string;
|
||||
|
||||
await runCli(
|
||||
["var", "set", `@ucas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
["var", "set", `@ocas/template/text/${schemaHash.trim()}`, tmplHash],
|
||||
tmpStore,
|
||||
);
|
||||
|
||||
@@ -342,7 +342,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("6.4 CLI with Non-templated Node (YAML Fallback)", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -379,7 +379,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("6.5 CLI Error: Invalid Decay Value", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -414,7 +414,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("R8: render with non-existent hash exits with error", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
const { exitCode, stderr, stdout } = await runCli(
|
||||
@@ -431,7 +431,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("R9: render with valid hash exits successfully", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -466,7 +466,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("R10: render --pipe with valid envelope succeeds", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -492,7 +492,7 @@ describe("Suite 6: CLI Integration with Templates", () => {
|
||||
});
|
||||
|
||||
test("R11: render --pipe with invalid type hash still renders", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
+19
-19
@@ -9,7 +9,7 @@ import { envValue, putSchemaFile, runCli } from "./helpers";
|
||||
describe("Issue #50: Schema Validation in put", () => {
|
||||
describe("Test Group 1: Valid Data (Regression Tests)", () => {
|
||||
test("T1.1: Valid data matching schema should be accepted", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -49,7 +49,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T1.2: Valid data with optional properties should be accepted", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -86,7 +86,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T1.3: Valid data with nested objects should be accepted", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -134,7 +134,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T1.4: Valid data using @ alias for type-hash should be accepted", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -156,7 +156,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
|
||||
describe("Test Group 2: Type Mismatches (New Validation)", () => {
|
||||
test("T2.1: Wrong property type should be rejected", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -200,7 +200,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T2.2: Missing required property should be rejected", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -234,7 +234,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T2.3: Additional properties when disallowed should be rejected", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -270,7 +270,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T2.4: Wrong root type should be rejected", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -302,7 +302,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T2.5: Nested type mismatch should be rejected", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -346,7 +346,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
|
||||
describe("Test Group 3: Schema Errors (Edge Cases)", () => {
|
||||
test("T3.1: Non-existent type-hash should fail gracefully", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -366,7 +366,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T3.3: Invalid @ alias should fail before validation", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -388,7 +388,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
|
||||
describe("Test Group 4: Integration with Existing Features", () => {
|
||||
test("T4.1: Hash command should not validate (dry-run consistency)", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -423,7 +423,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T4.2: Validation respects cas_ref format in schemas", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -466,7 +466,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T4.3: Schema self-validation still works", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -490,7 +490,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
|
||||
describe("Test Group 5: Error Message Quality", () => {
|
||||
test("T5.1: Error message should be helpful", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -522,7 +522,7 @@ describe("Issue #50: Schema Validation in put", () => {
|
||||
});
|
||||
|
||||
test("T5.2: Error should go to stderr, not stdout", async () => {
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "json-cas-test-"));
|
||||
const tmpStore = mkdtempSync(join(tmpdir(), "ocas-test-"));
|
||||
try {
|
||||
await runCli(["init"], tmpStore);
|
||||
|
||||
@@ -563,7 +563,7 @@ describe("Phase 2: Schema Validation", () => {
|
||||
const entrypoint = resolve(import.meta.dir, "../src/index.ts");
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -576,8 +576,8 @@ describe("Phase 2: Schema Validation", () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
||||
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { Hash, Store } from "@uncaged/json-cas";
|
||||
import { bootstrap } from "@uncaged/json-cas";
|
||||
import { createFsStore } from "@uncaged/json-cas-fs";
|
||||
import type { Hash, Store } from "@ocas/core";
|
||||
import { bootstrap } from "@ocas/core";
|
||||
import { createFsStore } from "@ocas/fs";
|
||||
|
||||
// ---- Test helpers ----
|
||||
|
||||
@@ -17,7 +17,7 @@ beforeEach(() => {
|
||||
// Create unique temp directory for each test
|
||||
testDir = join(
|
||||
tmpdir(),
|
||||
`json-cas-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
`ocas-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
);
|
||||
storePath = join(testDir, "store");
|
||||
varDbPath = join(testDir, "variables.db");
|
||||
@@ -403,7 +403,7 @@ describe("template list", () => {
|
||||
// Create a template
|
||||
await runCli("template", "set", stringHash, "--inline", "Template");
|
||||
|
||||
// Create a regular variable (not under @ucas/template/text/)
|
||||
// Create a regular variable (not under @ocas/template/text/)
|
||||
const hash = await store.put(stringHash, "regular var content");
|
||||
await runCli("var", "set", "regular/var", hash);
|
||||
|
||||
@@ -600,7 +600,7 @@ describe("template integration", () => {
|
||||
await runCli("template", "set", stringHash, "--inline", "Content");
|
||||
|
||||
// List via var command - should see template variable
|
||||
const { stdout } = await runCli("var", "list", "@ucas/template/text/");
|
||||
const { stdout } = await runCli("var", "list", "@ocas/template/text/");
|
||||
|
||||
const output = JSON.parse(stdout);
|
||||
expect(output.value.length).toBeGreaterThan(0);
|
||||
@@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
||||
import { mkdirSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { Hash, Store } from "@uncaged/json-cas";
|
||||
import { bootstrap, putSchema } from "@uncaged/json-cas";
|
||||
import { createFsStore } from "@uncaged/json-cas-fs";
|
||||
import type { Hash, Store } from "@ocas/core";
|
||||
import { bootstrap, putSchema } from "@ocas/core";
|
||||
import { createFsStore } from "@ocas/fs";
|
||||
|
||||
// ---- Test helpers ----
|
||||
|
||||
@@ -17,7 +17,7 @@ beforeEach(() => {
|
||||
// Create unique temp directory for each test
|
||||
testDir = join(
|
||||
tmpdir(),
|
||||
`json-cas-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
`ocas-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
||||
);
|
||||
storePath = join(testDir, "store");
|
||||
varDbPath = join(testDir, "variables.db");
|
||||
@@ -347,7 +347,7 @@ describe("var get", () => {
|
||||
const { stderr, exitCode } = await runCli("var", "get", "config");
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain("Usage: json-cas var get <name> --schema <hash>");
|
||||
expect(stderr).toContain("Usage: ocas var get <name> --schema <hash>");
|
||||
});
|
||||
|
||||
test("distinguish variants by schema", async () => {
|
||||
@@ -904,7 +904,7 @@ describe("var tag", () => {
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain(
|
||||
"Usage: json-cas var tag <name> --schema <hash> <operations...>",
|
||||
"Usage: ocas var tag <name> --schema <hash> <operations...>",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -922,7 +922,7 @@ describe("var tag", () => {
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain(
|
||||
"Usage: json-cas var tag <name> --schema <hash> <operations...>",
|
||||
"Usage: ocas var tag <name> --schema <hash> <operations...>",
|
||||
);
|
||||
});
|
||||
});
|
||||
+3
-3
@@ -12,7 +12,7 @@ let typeHash: string;
|
||||
let nodeHash: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "json-cas-e2e-"));
|
||||
tmpStore = mkdtempSync(join(tmpdir(), "ocas-e2e-"));
|
||||
varDbPath = join(tmpStore, "variables.db");
|
||||
|
||||
const schemaFile = join(tmpStore, "test-schema.json");
|
||||
@@ -25,8 +25,8 @@ beforeAll(async () => {
|
||||
additionalProperties: false,
|
||||
}),
|
||||
);
|
||||
const { openStore: openFsStore } = await import("@uncaged/json-cas-fs");
|
||||
const { putSchema } = await import("@uncaged/json-cas");
|
||||
const { openStore: openFsStore } = await import("@ocas/fs");
|
||||
const { putSchema } = await import("@ocas/core");
|
||||
const store = await openFsStore(tmpStore);
|
||||
typeHash = await putSchema(
|
||||
store,
|
||||
@@ -1,19 +1,19 @@
|
||||
# @uncaged/json-cas
|
||||
# @ocas/core
|
||||
|
||||
Core CAS engine — hashing, schema, store, verify, bootstrap.
|
||||
|
||||
## Overview
|
||||
|
||||
`@uncaged/json-cas` is the foundation of the json-cas monorepo. It defines content-addressed nodes (`CasNode`), the `Store` interface, XXH64-based hashing with deterministic CBOR, JSON Schema registration and validation (including `cas_ref` links between nodes), bootstrap seeding, and integrity verification.
|
||||
`@ocas/core` is the foundation of the ocas monorepo. It defines content-addressed nodes (`CasNode`), the `Store` interface, XXH64-based hashing with deterministic CBOR, JSON Schema registration and validation (including `cas_ref` links between nodes), bootstrap seeding, and integrity verification.
|
||||
|
||||
Other packages build on this layer: `json-cas-fs` provides persistence, and `cli-json-cas` exposes store operations on the command line.
|
||||
Other packages build on this layer: `ocas-fs` provides persistence, and `cli-ocas` exposes store operations on the command line.
|
||||
|
||||
**Dependencies:** `ajv`, `cborg`, `xxhash-wasm`
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @uncaged/json-cas
|
||||
bun add @ocas/core
|
||||
```
|
||||
|
||||
## API
|
||||
@@ -114,7 +114,7 @@ import {
|
||||
refs,
|
||||
validate,
|
||||
walk,
|
||||
} from "@uncaged/json-cas";
|
||||
} from "@ocas/core";
|
||||
|
||||
const store = createMemoryStore();
|
||||
const metaHash = await bootstrap(store);
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@uncaged/json-cas",
|
||||
"name": "@ocas/core",
|
||||
"version": "0.6.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Hash, Store } from "./types.js";
|
||||
|
||||
/** @internal Store implementations attach this for bootstrap() only. */
|
||||
export const BOOTSTRAP_STORE = Symbol.for("@uncaged/json-cas/bootstrap-store");
|
||||
export const BOOTSTRAP_STORE = Symbol.for("@ocas/core/bootstrap-store");
|
||||
|
||||
export type BootstrapCapableStore = Store & {
|
||||
[BOOTSTRAP_STORE](payload: unknown): Promise<Hash>;
|
||||
@@ -67,7 +67,7 @@ describe("bootstrap - Built-in Schemas", () => {
|
||||
const metaSchema = getSchema(store, metaHash);
|
||||
expect(metaSchema).not.toBeNull();
|
||||
expect(metaSchema?.type).toBe("object");
|
||||
expect(metaSchema?.description).toBe("json-cas JSON Schema meta-schema");
|
||||
expect(metaSchema?.description).toBe("ocas JSON Schema meta-schema");
|
||||
});
|
||||
|
||||
test("should register @string schema correctly", async () => {
|
||||
@@ -174,7 +174,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
const schema = getSchema(store, hash) as JSONSchema;
|
||||
expect(schema).not.toBeNull();
|
||||
expect(typeof schema.title).toBe("string");
|
||||
expect((schema.title as string).startsWith("ucas ")).toBe(true);
|
||||
expect((schema.title as string).startsWith("ocas ")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
expect(schema).toEqual({
|
||||
type: "string",
|
||||
format: "cas_ref",
|
||||
title: "ucas put result",
|
||||
title: "ocas put result",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -200,7 +200,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
|
||||
const schema = getSchema(store, hash) as JSONSchema;
|
||||
expect(schema.type).toBe("object");
|
||||
expect(schema.title).toBe("ucas get result");
|
||||
expect(schema.title).toBe("ocas get result");
|
||||
|
||||
const props = schema.properties as Record<string, JSONSchema>;
|
||||
expect(props.type).toEqual({ type: "string", format: "cas_ref" });
|
||||
@@ -216,7 +216,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
|
||||
expect(getSchema(store, hash)).toEqual({
|
||||
type: "boolean",
|
||||
title: "ucas has result",
|
||||
title: "ocas has result",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -230,7 +230,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
expect(schema).toEqual({
|
||||
type: "string",
|
||||
enum: ["ok", "corrupted", "invalid"],
|
||||
title: "ucas verify result",
|
||||
title: "ocas verify result",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -243,7 +243,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
expect(getSchema(store, hash)).toEqual({
|
||||
type: "array",
|
||||
items: { type: "string", format: "cas_ref" },
|
||||
title: "ucas refs result",
|
||||
title: "ocas refs result",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -255,7 +255,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
|
||||
const schema = getSchema(store, hash) as JSONSchema;
|
||||
expect(schema.type).toBe("object");
|
||||
expect(schema.title).toBe("ucas gc result");
|
||||
expect(schema.title).toBe("ocas gc result");
|
||||
|
||||
const props = schema.properties as Record<string, JSONSchema>;
|
||||
expect(props.total).toEqual({ type: "number" });
|
||||
@@ -272,7 +272,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
|
||||
const schema = getSchema(store, hash) as JSONSchema;
|
||||
expect(schema.type).toBe("object");
|
||||
expect(schema.title).toBe("ucas var set result");
|
||||
expect(schema.title).toBe("ocas var set result");
|
||||
|
||||
const props = schema.properties as Record<string, JSONSchema>;
|
||||
expect(props.name).toEqual({ type: "string" });
|
||||
@@ -288,7 +288,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
|
||||
const schema = getSchema(store, hash) as JSONSchema;
|
||||
expect(schema.type).toBe("array");
|
||||
expect(schema.title).toBe("ucas var list result");
|
||||
expect(schema.title).toBe("ocas var list result");
|
||||
|
||||
const items = schema.items as JSONSchema;
|
||||
expect(items.type).toBe("object");
|
||||
@@ -305,7 +305,7 @@ describe("bootstrap - @output/* Schemas", () => {
|
||||
expect(getSchema(store, hash)).toEqual({
|
||||
type: "object",
|
||||
properties: { deleted: { type: "boolean" } },
|
||||
title: "ucas template delete result",
|
||||
title: "ocas template delete result",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ const JSON_SCHEMA_TYPES = [
|
||||
const BOOTSTRAP_PAYLOAD = {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
description: "json-cas JSON Schema meta-schema",
|
||||
description: "ocas JSON Schema meta-schema",
|
||||
properties: {
|
||||
type: {
|
||||
anyOf: [
|
||||
@@ -121,7 +121,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
> = [
|
||||
[
|
||||
"@output/put",
|
||||
{ type: "string", format: "cas_ref", title: "ucas put result" },
|
||||
{ type: "string", format: "cas_ref", title: "ocas put result" },
|
||||
],
|
||||
[
|
||||
"@output/get",
|
||||
@@ -132,20 +132,20 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
payload: {},
|
||||
timestamp: { type: "number" },
|
||||
},
|
||||
title: "ucas get result",
|
||||
title: "ocas get result",
|
||||
},
|
||||
],
|
||||
["@output/has", { type: "boolean", title: "ucas has result" }],
|
||||
["@output/has", { type: "boolean", title: "ocas has result" }],
|
||||
[
|
||||
"@output/hash",
|
||||
{ type: "string", format: "cas_ref", title: "ucas hash result" },
|
||||
{ type: "string", format: "cas_ref", title: "ocas hash result" },
|
||||
],
|
||||
[
|
||||
"@output/verify",
|
||||
{
|
||||
type: "string",
|
||||
enum: ["ok", "corrupted", "invalid"],
|
||||
title: "ucas verify result",
|
||||
title: "ocas verify result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -153,7 +153,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "string", format: "cas_ref" },
|
||||
title: "ucas refs result",
|
||||
title: "ocas refs result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -161,7 +161,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
title: "ucas walk result",
|
||||
title: "ocas walk result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -169,7 +169,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "string", format: "cas_ref" },
|
||||
title: "ucas list result",
|
||||
title: "ocas list result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -177,7 +177,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "string", format: "cas_ref" },
|
||||
title: "ucas list-meta result",
|
||||
title: "ocas list-meta result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -185,7 +185,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "string", format: "cas_ref" },
|
||||
title: "ucas list-schema result",
|
||||
title: "ocas list-schema result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -193,7 +193,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "object",
|
||||
properties: { ...VARIABLE_PROPERTIES },
|
||||
title: "ucas var set result",
|
||||
title: "ocas var set result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -201,7 +201,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "object",
|
||||
properties: { ...VARIABLE_PROPERTIES },
|
||||
title: "ucas var get result",
|
||||
title: "ocas var get result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -209,7 +209,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "object",
|
||||
properties: { ...VARIABLE_PROPERTIES },
|
||||
title: "ucas var delete result",
|
||||
title: "ocas var delete result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -217,7 +217,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "object",
|
||||
properties: { ...VARIABLE_PROPERTIES },
|
||||
title: "ucas var tag result",
|
||||
title: "ocas var tag result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -225,7 +225,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "array",
|
||||
items: { type: "object", properties: { ...VARIABLE_PROPERTIES } },
|
||||
title: "ucas var list result",
|
||||
title: "ocas var list result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -236,12 +236,12 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
schemaHash: { type: "string", format: "cas_ref" },
|
||||
contentHash: { type: "string", format: "cas_ref" },
|
||||
},
|
||||
title: "ucas template set result",
|
||||
title: "ocas template set result",
|
||||
},
|
||||
],
|
||||
[
|
||||
"@output/template-get",
|
||||
{ type: "string", title: "ucas template get result" },
|
||||
{ type: "string", title: "ocas template get result" },
|
||||
],
|
||||
[
|
||||
"@output/template-list",
|
||||
@@ -254,7 +254,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
contentHash: { type: "string", format: "cas_ref" },
|
||||
},
|
||||
},
|
||||
title: "ucas template list result",
|
||||
title: "ocas template list result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -262,7 +262,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
{
|
||||
type: "object",
|
||||
properties: { deleted: { type: "boolean" } },
|
||||
title: "ucas template delete result",
|
||||
title: "ocas template delete result",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -275,7 +275,7 @@ const OUTPUT_SCHEMAS: ReadonlyArray<
|
||||
collected: { type: "number" },
|
||||
scanned: { type: "number" },
|
||||
},
|
||||
title: "ucas gc result",
|
||||
title: "ocas gc result",
|
||||
},
|
||||
],
|
||||
];
|
||||
+54
-54
@@ -11,7 +11,7 @@ import { createVariableStore } from "./variable-store.js";
|
||||
|
||||
// Helper to create a temporary variable store
|
||||
async function createTempVarStore() {
|
||||
const tempDir = await mkdtemp(join(tmpdir(), "json-cas-test-"));
|
||||
const tempDir = await mkdtemp(join(tmpdir(), "ocas-test-"));
|
||||
const dbPath = join(tempDir, "vars.db");
|
||||
const store = createMemoryStore();
|
||||
await bootstrap(store);
|
||||
@@ -92,14 +92,14 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"Parent: {{ payload.name }}\n{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, templateHash);
|
||||
|
||||
// Register template for child
|
||||
const childTemplateHash = await store.put(
|
||||
templateSchema,
|
||||
"Child: {{ payload.value }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplateHash);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplateHash);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 1.0,
|
||||
@@ -147,7 +147,7 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"Level {{ payload.level }}\n{% render payload.child, decay: 0.7 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, rootHash, {
|
||||
resolution: 1.0,
|
||||
@@ -195,13 +195,13 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"Left:\n{% render payload.left %}\nRight:\n{% render payload.right %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const childTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Value: {{ payload.value }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplate);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplate);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 1.0,
|
||||
@@ -242,7 +242,7 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"Before\n{% render payload.child %}\nAfter",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -281,7 +281,7 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -321,7 +321,7 @@ describe("Suite 2: Custom {% render %} Tag Implementation", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
// resolution=0.02, decay=0.5, child gets 0.01 which equals epsilon
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -356,7 +356,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
templateSchema,
|
||||
"Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 0.75,
|
||||
@@ -388,7 +388,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
templateSchema,
|
||||
"Epsilon: {{ epsilon }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -417,7 +417,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
|
||||
const templateSchema = await putSchema(store, { type: "string" });
|
||||
const template = await store.put(templateSchema, "Hash: {{ hash }}");
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -450,7 +450,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
templateSchema,
|
||||
"Name: {{ payload.name }}, Count: {{ payload.count }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -479,7 +479,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
|
||||
const templateSchema = await putSchema(store, { type: "string" });
|
||||
const template = await store.put(templateSchema, "Type: {{ type }}");
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -511,7 +511,7 @@ describe("Suite 3: Template Context Variables", () => {
|
||||
templateSchema,
|
||||
"Timestamp: {{ timestamp }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -548,7 +548,7 @@ Epsilon: {{ epsilon }}
|
||||
Payload: {{ payload.name }}
|
||||
Timestamp: {{ timestamp }}`,
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 0.8,
|
||||
@@ -587,7 +587,7 @@ describe("Suite 4: Render Flow Integration", () => {
|
||||
templateSchema,
|
||||
"Custom template: {{ payload.name }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -616,7 +616,7 @@ describe("Suite 4: Render Flow Integration", () => {
|
||||
|
||||
const templateSchema = await putSchema(store, { type: "string" });
|
||||
const template = await store.put(templateSchema, "");
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -648,7 +648,7 @@ describe("Suite 4: Render Flow Integration", () => {
|
||||
templateSchema,
|
||||
"{% render %}", // Invalid: no variable
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
await expect(async () => {
|
||||
await renderWithTemplate(store, varStore, nodeHash, {
|
||||
@@ -690,13 +690,13 @@ describe("Suite 5: Decay Priority Chain", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child, decay: 0.7 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const childTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplate);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplate);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 1.0,
|
||||
@@ -737,13 +737,13 @@ describe("Suite 5: Decay Priority Chain", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child %}", // No explicit decay
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const childTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplate);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplate);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 1.0,
|
||||
@@ -784,13 +784,13 @@ describe("Suite 5: Decay Priority Chain", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const childTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplate);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplate);
|
||||
|
||||
const output = await renderWithTemplate(
|
||||
store,
|
||||
@@ -837,7 +837,7 @@ describe("Suite 6: Recursive Rendering Edge Cases", () => {
|
||||
templateSchema,
|
||||
"Level {{ payload.level }}\n{% render payload.next %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(
|
||||
store,
|
||||
@@ -878,7 +878,7 @@ describe("Suite 6: Recursive Rendering Edge Cases", () => {
|
||||
templateSchema,
|
||||
"Node {{ payload.name }}\n{% render payload.ref %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeAHash, {
|
||||
resolution: 1.0,
|
||||
@@ -925,13 +925,13 @@ describe("Suite 6: Recursive Rendering Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% for item in payload.items %}{% render item %}\n{% endfor %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const itemTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Item: {{ payload.name }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${itemSchema}`, itemTemplate);
|
||||
varStore.set(`@ocas/template/text/${itemSchema}`, itemTemplate);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 1.0,
|
||||
@@ -967,7 +967,7 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% render missingVar %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
// Should complete without throwing
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
@@ -1008,7 +1008,7 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child, decay: 1.5 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, template);
|
||||
|
||||
await expect(async () => {
|
||||
await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -1048,7 +1048,7 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child, decay: -0.5 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, template);
|
||||
|
||||
await expect(async () => {
|
||||
await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -1088,7 +1088,7 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child, decay: 0 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, template);
|
||||
|
||||
await expect(async () => {
|
||||
await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -1128,13 +1128,13 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"{% render payload.child, decay: 1 %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const childTemplate = await store.put(
|
||||
templateSchema,
|
||||
"Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplate);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplate);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
resolution: 0.5,
|
||||
@@ -1167,7 +1167,7 @@ describe("Suite 7: Error Handling & Edge Cases", () => {
|
||||
templateSchema,
|
||||
"你好: {{ payload.name }} 🌍",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${nodeSchema}`, template);
|
||||
varStore.set(`@ocas/template/text/${nodeSchema}`, template);
|
||||
|
||||
const output = await renderWithTemplate(store, varStore, nodeHash, {
|
||||
resolution: 1.0,
|
||||
@@ -1217,13 +1217,13 @@ describe("Suite 8: Performance & Scalability", () => {
|
||||
templateSchema,
|
||||
"{% for child in payload.items %}{% render child %}{% endfor %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplate);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplate);
|
||||
|
||||
const itemTemplate = await store.put(
|
||||
templateSchema,
|
||||
"{{ payload.value }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${itemSchema}`, itemTemplate);
|
||||
varStore.set(`@ocas/template/text/${itemSchema}`, itemTemplate);
|
||||
|
||||
const start = Date.now();
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -1268,7 +1268,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Name: {{ name }}, Age: {{ age }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${personSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${personSchema}`, templateHash);
|
||||
|
||||
// Render - should produce empty values
|
||||
const output = await renderWithTemplate(store, varStore, personHash, {
|
||||
@@ -1309,7 +1309,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Name: {{ payload.name }}, Age: {{ payload.age }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${personSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${personSchema}`, templateHash);
|
||||
|
||||
// Render - should produce correct values
|
||||
const output = await renderWithTemplate(store, varStore, personHash, {
|
||||
@@ -1349,7 +1349,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"User: {{ payload.name }}, Age: {{ payload.age }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${personSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${personSchema}`, templateHash);
|
||||
|
||||
// This simulates the CLI flow
|
||||
const output = await renderWithTemplate(store, varStore, personHash, {
|
||||
@@ -1382,7 +1382,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Value is: {{ payload }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${stringSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${stringSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, stringHash, {
|
||||
@@ -1414,7 +1414,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"The answer is {{ payload }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${numberSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${numberSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, numberHash, {
|
||||
@@ -1469,7 +1469,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"User {{ payload.user.name }} lives in {{ payload.user.address.city }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${userSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${userSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, userHash, {
|
||||
@@ -1511,7 +1511,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Tags: {% for tag in payload.tags %}{{ tag }}{% unless forloop.last %}, {% endunless %}{% endfor %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${tagsSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${tagsSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, tagsHash, {
|
||||
@@ -1550,7 +1550,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Name: {{ payload.name }}, Age: {{ payload.age }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${personSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${personSchema}`, templateHash);
|
||||
|
||||
// Render - age should be empty
|
||||
const output = await renderWithTemplate(store, varStore, personHash, {
|
||||
@@ -1591,7 +1591,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Name: {{ payload.name }}, Email: {{ payload.email }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${personSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${personSchema}`, templateHash);
|
||||
|
||||
// Render - email should be empty
|
||||
const output = await renderWithTemplate(store, varStore, personHash, {
|
||||
@@ -1632,7 +1632,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"User {{ payload.name }} is {% if payload.active %}active{% else %}inactive{% endif %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${userSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${userSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, userHash, {
|
||||
@@ -1673,7 +1673,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Name: '{{ payload.name }}', Count: {{ payload.count }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${dataSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${dataSchema}`, templateHash);
|
||||
|
||||
// Render - zero and empty string should appear
|
||||
const output = await renderWithTemplate(store, varStore, dataHash, {
|
||||
@@ -1712,7 +1712,7 @@ describe("Suite 9: E2E Template Variable Rendering (Issue #52)", () => {
|
||||
templateSchema,
|
||||
"Text: {{ payload.text }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${textSchema}`, templateHash);
|
||||
varStore.set(`@ocas/template/text/${textSchema}`, templateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, textHash, {
|
||||
@@ -1762,14 +1762,14 @@ describe("Suite 10: Context Variable Completeness", () => {
|
||||
templateSchema,
|
||||
"Parent: {{ payload.name }}\n{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplateHash);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplateHash);
|
||||
|
||||
// Register child template that accesses context variables
|
||||
const childTemplateHash = await store.put(
|
||||
templateSchema,
|
||||
"Child: {{ payload.name }}, Hash: {{ hash }}, Resolution: {{ resolution }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplateHash);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -1822,14 +1822,14 @@ describe("Suite 10: Context Variable Completeness", () => {
|
||||
templateSchema,
|
||||
"Parent custom: {{ payload.custom }}\n{% render payload.child %}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${parentSchema}`, parentTemplateHash);
|
||||
varStore.set(`@ocas/template/text/${parentSchema}`, parentTemplateHash);
|
||||
|
||||
// Register child template
|
||||
const childTemplateHash = await store.put(
|
||||
templateSchema,
|
||||
"Child custom: {{ payload.custom }}",
|
||||
);
|
||||
varStore.set(`@ucas/template/text/${childSchema}`, childTemplateHash);
|
||||
varStore.set(`@ocas/template/text/${childSchema}`, childTemplateHash);
|
||||
|
||||
// Render
|
||||
const output = await renderWithTemplate(store, varStore, parentHash, {
|
||||
@@ -11,7 +11,7 @@ const FLOAT_TOLERANCE = 1e-10;
|
||||
|
||||
/**
|
||||
* Render a CAS node using LiquidJS templates with resolution-based decay.
|
||||
* Templates are discovered via variables: @ucas/template/text/<type-hash>
|
||||
* Templates are discovered via variables: @ocas/template/text/<type-hash>
|
||||
*/
|
||||
export async function renderWithTemplate(
|
||||
store: Store,
|
||||
@@ -220,7 +220,7 @@ async function findTemplate(
|
||||
varStore: VariableStore,
|
||||
typeHash: Hash,
|
||||
): Promise<string | null> {
|
||||
const varName = `@ucas/template/text/${typeHash}`;
|
||||
const varName = `@ocas/template/text/${typeHash}`;
|
||||
|
||||
try {
|
||||
// Find the string schema hash (we need this to query variables)
|
||||
+7
-7
@@ -41,7 +41,7 @@ describe("registerOutputTemplates", () => {
|
||||
});
|
||||
|
||||
test("registers a template for every @output/* schema", async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), "json-cas-tmpl-"));
|
||||
tempDir = await mkdtemp(join(tmpdir(), "ocas-tmpl-"));
|
||||
store = createMemoryStore();
|
||||
await bootstrap(store);
|
||||
varStore = createVariableStore(join(tempDir, "vars.db"), store);
|
||||
@@ -55,8 +55,8 @@ describe("registerOutputTemplates", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("each template is retrievable via @ucas/template/text/<hash>", async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), "json-cas-tmpl-"));
|
||||
test("each template is retrievable via @ocas/template/text/<hash>", async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), "ocas-tmpl-"));
|
||||
store = createMemoryStore();
|
||||
const aliases = await bootstrap(store);
|
||||
varStore = createVariableStore(join(tempDir, "vars.db"), store);
|
||||
@@ -70,7 +70,7 @@ describe("registerOutputTemplates", () => {
|
||||
const schemaHash = aliases[alias];
|
||||
if (!schemaHash) throw new Error(`${alias} not found`);
|
||||
|
||||
const varName = `@ucas/template/text/${schemaHash}`;
|
||||
const varName = `@ocas/template/text/${schemaHash}`;
|
||||
const variable = varStore.get(varName, stringHash);
|
||||
if (variable === null) throw new Error(`Variable ${varName} not found`);
|
||||
|
||||
@@ -82,7 +82,7 @@ describe("registerOutputTemplates", () => {
|
||||
});
|
||||
|
||||
test("is idempotent — safe to call multiple times", async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), "json-cas-tmpl-"));
|
||||
tempDir = await mkdtemp(join(tmpdir(), "ocas-tmpl-"));
|
||||
store = createMemoryStore();
|
||||
await bootstrap(store);
|
||||
varStore = createVariableStore(join(tempDir, "vars.db"), store);
|
||||
@@ -94,7 +94,7 @@ describe("registerOutputTemplates", () => {
|
||||
});
|
||||
|
||||
test("@output/put template contains payload reference", async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), "json-cas-tmpl-"));
|
||||
tempDir = await mkdtemp(join(tmpdir(), "ocas-tmpl-"));
|
||||
store = createMemoryStore();
|
||||
const aliases = await bootstrap(store);
|
||||
varStore = createVariableStore(join(tempDir, "vars.db"), store);
|
||||
@@ -106,7 +106,7 @@ describe("registerOutputTemplates", () => {
|
||||
const stringHash = aliases["@string"];
|
||||
if (!stringHash) throw new Error("@string not found");
|
||||
|
||||
const variable = varStore.get(`@ucas/template/text/${putHash}`, stringHash);
|
||||
const variable = varStore.get(`@ocas/template/text/${putHash}`, stringHash);
|
||||
if (variable === null)
|
||||
throw new Error("@output/put template variable not found");
|
||||
|
||||
@@ -55,7 +55,7 @@ const DEFAULT_TEMPLATES: ReadonlyArray<
|
||||
/**
|
||||
* Register default LiquidJS templates for all @output/* schemas.
|
||||
* Each template is stored as a @string CAS node and bound to
|
||||
* the variable `@ucas/template/text/<schema-hash>`.
|
||||
* the variable `@ocas/template/text/<schema-hash>`.
|
||||
*
|
||||
* Idempotent: safe to call multiple times.
|
||||
*/
|
||||
@@ -78,7 +78,7 @@ export async function registerOutputTemplates(
|
||||
}
|
||||
|
||||
const contentHash = await store.put(stringHash, template);
|
||||
const varName = `@ucas/template/text/${schemaHash}`;
|
||||
const varName = `@ocas/template/text/${schemaHash}`;
|
||||
varStore.set(varName, contentHash);
|
||||
registered[alias] = contentHash;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ async function hasTemplate(
|
||||
varStore: VariableStore,
|
||||
typeHash: Hash,
|
||||
): Promise<boolean> {
|
||||
const varName = `@ucas/template/text/${typeHash}`;
|
||||
const varName = `@ocas/template/text/${typeHash}`;
|
||||
try {
|
||||
const stringSchema = await putSchema(store, { type: "string" });
|
||||
const variable = varStore.get(varName, stringSchema);
|
||||
@@ -259,7 +259,7 @@ export async function putSchema(
|
||||
}
|
||||
if (!isValidSchema(jsonSchema)) {
|
||||
throw new SchemaValidationError(
|
||||
"Invalid schema: input does not conform to the json-cas JSON Schema meta-schema",
|
||||
"Invalid schema: input does not conform to the ocas JSON Schema meta-schema",
|
||||
);
|
||||
}
|
||||
return store.put(metaHash, jsonSchema);
|
||||
+5
-5
@@ -1622,12 +1622,12 @@ describe("VariableStore - @ Prefix Variable Names", () => {
|
||||
const varStore = new VariableStore(dbPath, store);
|
||||
|
||||
// Should succeed
|
||||
const variable = varStore.set("@ucas/test/foo", hash);
|
||||
expect(variable.name).toBe("@ucas/test/foo");
|
||||
const variable = varStore.set("@ocas/test/foo", hash);
|
||||
expect(variable.name).toBe("@ocas/test/foo");
|
||||
|
||||
const retrieved = varStore.get("@ucas/test/foo", schemaHash);
|
||||
const retrieved = varStore.get("@ocas/test/foo", schemaHash);
|
||||
expect(retrieved).not.toBeNull();
|
||||
expect(retrieved?.name).toBe("@ucas/test/foo");
|
||||
expect(retrieved?.name).toBe("@ocas/test/foo");
|
||||
expect(retrieved?.value).toBe(hash);
|
||||
|
||||
varStore.close();
|
||||
@@ -1662,7 +1662,7 @@ describe("VariableStore - @ Prefix Variable Names", () => {
|
||||
|
||||
// Multiple valid patterns
|
||||
const validNames = [
|
||||
"@ucas/render/template",
|
||||
"@ocas/render/template",
|
||||
"@system/config",
|
||||
"@foo.bar/baz",
|
||||
"@app-1/test_2",
|
||||
@@ -1,19 +1,19 @@
|
||||
# @uncaged/json-cas-fs
|
||||
# @ocas/fs
|
||||
|
||||
Filesystem-backed CAS store.
|
||||
|
||||
## Overview
|
||||
|
||||
`@uncaged/json-cas-fs` implements a persistent `Store` on disk. Each node is stored as `<hash>.bin` (CBOR-encoded `CasNode`). A `_index/` directory maps type hashes to content hashes for `listByType`. Stores support bootstrap via the same `BOOTSTRAP_STORE` symbol as the in-memory implementation.
|
||||
`@ocas/fs` implements a persistent `Store` on disk. Each node is stored as `<hash>.bin` (CBOR-encoded `CasNode`). A `_index/` directory maps type hashes to content hashes for `listByType`. Stores support bootstrap via the same `BOOTSTRAP_STORE` symbol as the in-memory implementation.
|
||||
|
||||
Depends on `@uncaged/json-cas` for hashing, CBOR encoding, and types.
|
||||
Depends on `@ocas/core` for hashing, CBOR encoding, and types.
|
||||
|
||||
**Dependencies:** `@uncaged/json-cas`, `cborg`
|
||||
**Dependencies:** `@ocas/core`, `cborg`
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @uncaged/json-cas-fs
|
||||
bun add @ocas/fs
|
||||
```
|
||||
|
||||
## API
|
||||
@@ -24,13 +24,13 @@ Exported from `src/index.ts`:
|
||||
function createFsStore(dir: string): BootstrapCapableStore;
|
||||
```
|
||||
|
||||
Returns a `BootstrapCapableStore` from `@uncaged/json-cas`. The store loads existing `.bin` files on open and migrates or builds the type index on first use.
|
||||
Returns a `BootstrapCapableStore` from `@ocas/core`. The store loads existing `.bin` files on open and migrates or builds the type index on first use.
|
||||
|
||||
### Example
|
||||
|
||||
```typescript
|
||||
import { bootstrap, putSchema } from "@uncaged/json-cas";
|
||||
import { createFsStore } from "@uncaged/json-cas-fs";
|
||||
import { bootstrap, putSchema } from "@ocas/core";
|
||||
import { createFsStore } from "@ocas/fs";
|
||||
|
||||
const store = createFsStore("./my-cas-store");
|
||||
await bootstrap(store);
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@uncaged/json-cas-fs",
|
||||
"name": "@ocas/fs",
|
||||
"version": "0.6.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
@@ -19,7 +19,7 @@
|
||||
"prepublishOnly": "bash ../../scripts/check-workspace-deps.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uncaged/json-cas": "^0.6.0",
|
||||
"cborg": "^4.2.3"
|
||||
"cborg": "^4.2.3",
|
||||
"@ocas/core": "^0.6.0"
|
||||
}
|
||||
}
|
||||
@@ -9,19 +9,19 @@ import {
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { CasNode } from "@uncaged/json-cas";
|
||||
import type { CasNode } from "@ocas/core";
|
||||
import {
|
||||
BOOTSTRAP_STORE,
|
||||
bootstrap,
|
||||
computeHash,
|
||||
computeSelfHash,
|
||||
verify,
|
||||
} from "@uncaged/json-cas";
|
||||
} from "@ocas/core";
|
||||
|
||||
import { createFsStore, openStore } from "./store.js";
|
||||
|
||||
function makeTmpDir(): string {
|
||||
return mkdtempSync(join(tmpdir(), "json-cas-fs-test-"));
|
||||
return mkdtempSync(join(tmpdir(), "ocas-fs-test-"));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
@@ -438,7 +438,7 @@ describe("openStore – async with auto-bootstrap", () => {
|
||||
describe("createFsStore – listMeta and listSchemas", () => {
|
||||
let dir: string;
|
||||
beforeEach(() => {
|
||||
dir = mkdtempSync(join(tmpdir(), "json-cas-fs-meta-"));
|
||||
dir = mkdtempSync(join(tmpdir(), "ocas-fs-meta-"));
|
||||
});
|
||||
afterEach(() => {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type { BootstrapCapableStore, CasNode, Hash } from "@uncaged/json-cas";
|
||||
import type { BootstrapCapableStore, CasNode, Hash } from "@ocas/core";
|
||||
|
||||
import {
|
||||
BOOTSTRAP_STORE,
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
cborEncode,
|
||||
computeHash,
|
||||
computeSelfHash,
|
||||
} from "@uncaged/json-cas";
|
||||
} from "@ocas/core";
|
||||
import { decode } from "cborg";
|
||||
|
||||
const INDEX_DIR = "_index";
|
||||
@@ -6,5 +6,5 @@
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["src/**/*.test.ts"],
|
||||
"references": [{ "path": "../json-cas" }]
|
||||
"references": [{ "path": "../core" }]
|
||||
}
|
||||
+2
-2
@@ -11,8 +11,8 @@
|
||||
"verbatimModuleSyntax": true,
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@uncaged/json-cas": ["./packages/json-cas/src/index.ts"],
|
||||
"@uncaged/json-cas-fs": ["./packages/json-cas-fs/src/index.ts"]
|
||||
"@ocas/core": ["./packages/core/src/index.ts"],
|
||||
"@ocas/fs": ["./packages/fs/src/index.ts"]
|
||||
},
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
|
||||
Reference in New Issue
Block a user