The REST API returns a clone as a giant `files` map JSON blob with no
first-party way to use it — users were left staring at kilobytes of
escaped JSON with no path from "you got JSON" to "here's a project".
Add packages/cli: a zero-dependency `ditto` CLI whose `unpack` command
walks the files{} map from POST /v1/clones (or GET .../result) and
writes a real project tree to disk:
- text files written from inline content;
- binary assets materialized from inline base64, else fetched from their
reference URL using $DITTO_API_URL / $DITTO_API_KEY (--no-fetch writes
just the text tree and lists skipped assets);
- path-traversal guards (clone results are untrusted) and sha256
integrity checks;
- reads JSON from stdin ("-") so a curl response pipes straight in;
- clear errors for queued jobs with no files yet, and a tip pointing at
the /bundle endpoint when assets can't be fetched.
Document the pipe-from-curl one-liner prominently next to the REST
examples in README.md and docs/SERVICE.md, add a package README, a
Repository Map row, a root `unpack` script, and a CHANGELOG entry.
Covered by 9 tests (text tree, stdin, inline base64, live URL fetch with
auth + relative-URL resolution, --no-fetch, traversal refusal, queued-job
detection, sha256 mismatch).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
56 lines
1.7 KiB
JSON
56 lines
1.7 KiB
JSON
{
|
|
"name": "ditto.site",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"description": "ditto.site deterministic website compiler: compile a public URL into a Next.js app from browser-captured evidence with a REST + MCP service layer.",
|
|
"license": "MIT",
|
|
"author": "ion-design",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/ion-design/ditto.site.git"
|
|
},
|
|
"bugs": {
|
|
"url": "https://github.com/ion-design/ditto.site/issues"
|
|
},
|
|
"homepage": "https://github.com/ion-design/ditto.site#readme",
|
|
"keywords": [
|
|
"ditto.site",
|
|
"website-compiler",
|
|
"nextjs",
|
|
"playwright",
|
|
"deterministic",
|
|
"compiler",
|
|
"mcp",
|
|
"hono",
|
|
"drizzle"
|
|
],
|
|
"type": "module",
|
|
"packageManager": "npm@10.9.2",
|
|
"workspaces": [
|
|
"compiler",
|
|
"packages/*"
|
|
],
|
|
"scripts": {
|
|
"clone": "npm run clone --workspace clone-static --",
|
|
"clone-site": "npm run clone-site --workspace clone-static --",
|
|
"validate-site": "npm run validate-site --workspace clone-static --",
|
|
"bench": "npm run bench --workspace clone-static --",
|
|
"bench-site": "npm run bench-site --workspace clone-static --",
|
|
"test": "npm run test --workspaces --if-present",
|
|
"typecheck": "npm run typecheck --workspaces --if-present",
|
|
"dev:api": "npm run dev --workspace @cloner/api",
|
|
"dev:worker": "npm run dev --workspace @cloner/worker",
|
|
"db:generate": "npm run generate --workspace @cloner/db",
|
|
"db:migrate": "npm run migrate --workspace @cloner/db",
|
|
"unpack": "node packages/cli/bin/ditto.mjs unpack"
|
|
},
|
|
"devDependencies": {
|
|
"tsx": "4.22.4",
|
|
"typescript": "5.7.3",
|
|
"@types/node": "22.10.5"
|
|
},
|
|
"engines": {
|
|
"node": ">=20"
|
|
}
|
|
}
|