Files
abode/package.json
T
codingetandClaude ccb970f200
CI / format (pull_request) Successful in 28s
CI / lint (pull_request) Successful in 28s
CI / install-and-build (pull_request) Successful in 53s
CI / typecheck-tests (pull_request) Successful in 28s
CI / typecheck-source (pull_request) Successful in 32s
CI / test (pull_request) Successful in 43s
feat: add export/import streaming to the pluggable backends
Add backend-agnostic data export/import over an NDJSON wire format, plus an
inspect utility, exposed via three new CLIs and an HTTP export endpoint.

- ExportImport types + filter helpers (kind/record scoping, hard-intersection
  of filters) in src/db/{types/ExportImport,export/filter}.ts
- SqliteInterface implements Exportable + Importable: signal-checked async
  generator export (one query per table, per-record yield, trailing error
  sentinel on mid-stream failure) and a manually-driven import transaction
  that rolls back on any error/abort and never commits partial data
- ApiInterface implements Exportable via its own fetch({signal})
- computeForcedExportFilter enforces non-global-admin scope (resided-in abodes
  + co-resident users, intersected with apikey restrict_*); GET /export
  intersects it with the caller's filter and wires an AbortController to the
  response socket
- inspectExportStream reports kinds/counts from any stream without a db
- abode-export / abode-import / abode-inspect CLIs (import is sqlite-only)
- Secrets are not exported: imported users default to '#unset' passwords and
  apikeys are re-minted a token (ClientApikey view round-trips exactly)
- test/tools/export-import.test.ts: round-trip, filter narrowing, forced-scope,
  export/import cancellation, in-process Koa endpoint, inspect

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 22:29:03 +00:00

85 lines
3.4 KiB
JSON

{
"name": "abode",
"version": "0.1.0",
"description": "A management interface for household stuff",
"author": "Codinget <codinget@codi.moe>",
"license": "ISC",
"type": "module",
"bin": {
"abode-migrate": "dist/bin/abode-migrate.cjs",
"abode-repl": "dist/bin/abode-repl.cjs",
"abode-web": "dist/bin/abode-web.cjs",
"abode-tui": "dist/bin/abode-tui.cjs",
"abode-export": "dist/bin/abode-export.cjs",
"abode-import": "dist/bin/abode-import.cjs",
"abode-inspect": "dist/bin/abode-inspect.cjs"
},
"scripts": {
"repl": "tsx --import ./src/meta/dev/register.ts",
"abode-migrate": "tsx --import ./src/meta/dev/register.ts src/bin/abode-migrate.ts",
"abode-repl": "tsx --import ./src/meta/dev/register.ts src/bin/abode-repl.ts",
"abode-web": "tsx --import ./src/meta/dev/register.ts --import ./src/meta/dev/webhot.ts src/bin/abode-web.ts",
"abode-tui": "tsx --import ./src/meta/dev/register.ts --import ./src/meta/dev/silenthot.ts src/bin/abode-tui.ts",
"abode-sources": "tsx --import ./src/meta/dev/register.ts src/bin/abode-sources.ts",
"abode-export": "tsx --import ./src/meta/dev/register.ts src/bin/abode-export.ts",
"abode-import": "tsx --import ./src/meta/dev/register.ts src/bin/abode-import.ts",
"abode-inspect": "tsx --import ./src/meta/dev/register.ts src/bin/abode-inspect.ts",
"build": "NODE_ENV=production npm run build:impl",
"build:impl": "rm -rf dist && tsx node_modules/.bin/webpack && chmod +x dist/bin/* && chmod -x dist/bin/*.*",
"test": "node --import tsx/esm --import ./src/meta/dev/register.ts --test $(find test -name '*.test.ts' | sort)",
"test:backends": "node --import tsx/esm --import ./src/meta/dev/register.ts --test $(find test/backends -name '*.test.ts' | sort)",
"test:shared": "node --import tsx/esm --import ./src/meta/dev/register.ts --test $(find test/backends -name 'index.test.ts' | sort)",
"test:tools": "node --import tsx/esm --import ./src/meta/dev/register.ts --test $(find test/tools -name '*.test.ts' | sort)",
"typecheck": "tsc --noEmit",
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
"lint": "eslint .",
"format:check": "prettier --check ."
},
"dependencies": {
"@koa/bodyparser": "^6.0.0",
"@koa/router": "^14.0.0",
"@reduxjs/toolkit": "^2.9.0",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"fullscreen-ink": "^0.1.0",
"hash-wasm": "^4.12.0",
"ink": "^6.3.0",
"ink-text-input": "^6.0.0",
"koa": "^3.0.1",
"pg": "^8.16.3",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-redux": "^9.2.0"
},
"devDependencies": {
"@eslint/js": "^9.39.5",
"@types/better-sqlite3": "^7.6.13",
"@types/koa": "^3.0.0",
"@types/koa__router": "^12.0.4",
"@types/pg": "^8.20.0",
"@types/react": "^19.1.12",
"@types/webpack-bundle-analyzer": "^4.7.0",
"copy-webpack-plugin": "^13.0.1",
"css-loader": "^7.1.2",
"dynohot": "^2.1.1",
"eslint": "^9.39.5",
"mini-css-extract-plugin": "^2.9.4",
"prettier": "^3.6.2",
"raw-loader": "^4.0.2",
"scss-loader": "^0.0.1",
"ts-loader": "^9.5.4",
"tsx": "^4.20.5",
"typescript": "^5.9.2",
"typescript-eslint": "^8.65.0",
"val-loader": "^6.0.0",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "^6.0.1"
},
"engines": {
"node": "^22"
},
"optionalDependencies": {
"better-sqlite3": "^12.2.0"
}
}