thatcher 1.0.41 → 1.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/package.json +2 -5
- package/src/app/api/audit/dashboard/route.js +2 -2
- package/src/app/api/audit/logs/route.js +2 -2
- package/src/app/api/audit/permissions/[id]/route.js +2 -2
- package/src/app/api/audit/permissions/route.js +3 -3
- package/src/app/api/audit/permissions/stats/route.js +2 -2
- package/src/app/api/audit/route.js +2 -3
- package/src/app/api/audit/stats/route.js +2 -2
- package/src/app/api/auth/google/callback/route.js +1 -1
- package/src/app/api/auth/google/route.js +1 -1
- package/src/app/api/auth/login/route.js +1 -1
- package/src/app/api/auth/logout/route.js +1 -1
- package/src/app/api/auth/me/route.js +1 -1
- package/src/app/api/auth/mwr-bridge/route.js +1 -1
- package/src/app/api/auth/password-reset/route.js +1 -1
- package/src/app/api/csrf-token/route.js +1 -1
- package/src/app/api/debug/[[...path]]/route.js +2 -2
- package/src/app/api/debug/config/route.js +1 -1
- package/src/app/api/debug/hooks/route.js +1 -1
- package/src/app/api/debug/plugins/route.js +1 -1
- package/src/app/api/debug/sqlite/route.js +1 -1
- package/src/app/api/debug/sync/route.js +1 -1
- package/src/app/api/debug/workflow/route.js +1 -1
- package/src/app/api/domains/[domain]/route.js +1 -2
- package/src/app/api/domains/route.js +1 -1
- package/src/app/api/email/allocate/batch/route.js +1 -1
- package/src/app/api/email/allocate/route.js +1 -1
- package/src/app/api/email/receive/route.js +1 -1
- package/src/app/api/email/send/route.js +1 -1
- package/src/app/api/email/unallocated/route.js +1 -1
- package/src/app/api/files/[id]/route.js +1 -1
- package/src/app/api/health/route.js +1 -2
- package/src/app/api/metrics/route.js +1 -2
- package/src/engine.js +3 -3
- package/src/engine.server.js +3 -3
- package/src/index.js +9 -9
- package/src/lib/action-factory.js +1 -1
- package/src/lib/api-helpers.js +1 -1
- package/src/lib/api.js +3 -4
- package/src/lib/audit-logger-enhanced.js +1 -1
- package/src/lib/auth-middleware.js +1 -1
- package/src/lib/auth-route-helpers.js +1 -1
- package/src/lib/{busybase-adapter.js → busybase/adapter.js} +3 -3
- package/src/lib/{busybase-audit-reads.js → busybase/audit-reads.js} +1 -1
- package/src/lib/{busybase-audit.js → busybase/audit.js} +2 -2
- package/src/lib/{busybase-lucia-adapter.js → busybase/lucia-adapter.js} +1 -1
- package/src/lib/{busybase-store.js → busybase/store.js} +3 -3
- package/src/lib/config-generator-engine.js +13 -1
- package/src/lib/crud-action-helpers.js +1 -1
- package/src/lib/crud-handlers.js +4 -4
- package/src/lib/email-sender.js +1 -1
- package/src/lib/errors/index.js +3 -0
- package/src/lib/{error-recovery.js → errors/recovery.js} +120 -4
- package/src/lib/{error-handler.js → errors/types.js} +1 -1
- package/src/lib/errors/wrap.js +225 -0
- package/src/lib/events-engine.js +1 -1
- package/src/lib/hot-reload/index.js +34 -0
- package/src/lib/index.js +5 -5
- package/src/lib/keyed-cache.js +112 -0
- package/src/lib/monitor.js +285 -0
- package/src/lib/next-shim.js +294 -0
- package/src/lib/observability-init.js +213 -0
- package/src/lib/perf.js +468 -0
- package/src/lib/query-cache.js +40 -46
- package/src/lib/realtime-server.js +18 -0
- package/src/lib/render-cache.js +14 -28
- package/src/lib/{request-tracing.js → request-trace.js} +57 -2
- package/src/lib/response-formatter.js +18 -0
- package/src/lib/route-helpers.js +1 -1
- package/src/lib/state-protocol.js +13 -0
- package/src/lib/state-transport-client.js +6 -0
- package/src/lib/state-transport-reconnect.js +5 -0
- package/src/lib/state-transport-server.js +8 -0
- package/src/lib/utils.js +1 -1
- package/src/lib/{validate.js → validation/entity-validators.js} +9 -8
- package/src/lib/validation/index.js +1 -1
- package/src/lib/validation/security-validators.js +1 -1
- package/src/lib/validation-middleware.js +2 -2
- package/src/lib/workflow-engine.js +23 -3
- package/src/lib/xstate-workflow-engine.js +18 -2
- package/src/services/collaborator-role.service.js +2 -2
- package/src/services/notification-engine.js +5 -5
- package/src/services/permission.service.js +1 -1
- package/src/ui/format-helpers.js +1 -4
- package/src/ui/highlight-threading-renderer.js +1 -1
- package/src/ui/page-handler-admin.js +6 -5
- package/src/ui/page-handler-helpers.js +2 -2
- package/src/ui/page-handler-reviews.js +4 -4
- package/src/ui/page-handler-rfi.js +1 -1
- package/src/ui/page-handler.js +2 -2
- package/src/ui/render-helpers.js +1 -1
- package/src/ui/renderer.js +1 -1
- package/src/ui/{review-comparison-renderer.js → review/comparison.js} +1 -1
- package/src/ui/{review-detail-renderer.js → review/detail-renderer.js} +3 -3
- package/src/ui/review/index.js +32 -0
- package/src/ui/{review-mwr-renderer.js → review/mwr.js} +1 -1
- package/src/ui/{review-renderer.js → review/renderer.js} +1 -1
- package/src/ui/{settings-renderer.js → settings/home.js} +7 -34
- package/src/ui/{settings-renderer-advanced.js → settings/review.js} +117 -56
- package/src/ui/settings/shared.js +45 -0
- package/src/ui/{settings-renderer-teams.js → settings/teams.js} +1 -2
- package/src/ui/settings/templates.js +116 -0
- package/src/lib/api-error-wrapper.js +0 -125
- package/src/lib/db-monitor.js +0 -127
- package/src/lib/error-resilience.js +0 -132
- package/src/lib/monitoring-init.js +0 -67
- package/src/lib/next-compat.js +0 -94
- package/src/lib/next-polyfills.js +0 -135
- package/src/lib/observability-bootstrap.js +0 -116
- package/src/lib/perf-monitor.js +0 -94
- package/src/lib/perf-profiler.js +0 -233
- package/src/lib/query-perf.js +0 -117
- package/src/lib/request-tracker.js +0 -43
- package/src/lib/resource-monitor.js +0 -120
- package/src/lib/validators.js +0 -67
- package/src/lib/with-error-handler.js +0 -31
- package/src/ui/settings-renderer-advanced2.js +0 -159
- /package/src/ui/{review-detail-panels.js → review/detail-panels.js} +0 -0
- /package/src/ui/{review-detail-script.js → review/detail-script.js} +0 -0
- /package/src/ui/{review-widgets.js → review/widgets.js} +0 -0
- /package/src/ui/{review-zone-nav.js → review/zone-nav.js} +0 -0
package/README.md
CHANGED
|
@@ -380,6 +380,33 @@ Thatcher is published to npm as `thatcher`. Every push to `main` triggers:
|
|
|
380
380
|
|
|
381
381
|
CI/CD ready via included GitHub Actions workflow.
|
|
382
382
|
|
|
383
|
+
## Runtime: Bun vs Node
|
|
384
|
+
|
|
385
|
+
Thatcher targets Bun as its primary runtime (`engines.bun` in `package.json`,
|
|
386
|
+
a `bun.lock` in the repo root, and `src/cli.js` carries a `#!/usr/bin/env bun`
|
|
387
|
+
shebang), but most of the codebase is plain ES modules with no Bun-only API
|
|
388
|
+
calls, so a Node-only consumer can run everything except the two `bun run`
|
|
389
|
+
scripts as-is.
|
|
390
|
+
|
|
391
|
+
| Script | Command | Runtime |
|
|
392
|
+
|--------|---------|---------|
|
|
393
|
+
| `npm run dev` | `bun run src/cli.js dev` | **Bun required** — invoked via `bun run`; `thatcher dev` also enables hot reload (`server.hotReload: true`), and the CLI's own shebang is `#!/usr/bin/env bun`. |
|
|
394
|
+
| `npm run start` | `bun run src/cli.js start` | **Bun required** — same `bun run` invocation as `dev`, just without hot reload. |
|
|
395
|
+
| `npm test` | `node test.js` | Plain Node — runs fine under `node test.js` directly. |
|
|
396
|
+
| `npm run lint` | `eslint src/` | Tool-agnostic — standard ESLint CLI, no runtime dependency. |
|
|
397
|
+
| `npm run typecheck` | `tsc --noEmit` | Tool-agnostic — standard TypeScript CLI. |
|
|
398
|
+
|
|
399
|
+
In practice, `src/cli.js` itself has no Bun-only API calls (no `Bun.*`
|
|
400
|
+
globals) — the `bun run` wrapping in `dev`/`start` is a process-launcher
|
|
401
|
+
choice, not a hard code dependency, so `node src/cli.js start` / `node
|
|
402
|
+
src/cli.js dev` also work for a Node-only deployer. The one place Bun is
|
|
403
|
+
harder to avoid is the `busybase` dependency, whose published `src/*.js` are
|
|
404
|
+
bun-build outputs (per its own build process) rather than hand-authored
|
|
405
|
+
Node-targeted files. A Node-only consumer/deployer can therefore run
|
|
406
|
+
`test`/`lint`/`typecheck` and the CLI itself with plain `node`, but should
|
|
407
|
+
expect the `dev`/`start` npm scripts as published to require Bun on `PATH`
|
|
408
|
+
unless invoking `src/cli.js` directly with `node`.
|
|
409
|
+
|
|
383
410
|
## License
|
|
384
411
|
|
|
385
412
|
MIT — Extracted from moonlanding with all functionality preserved.
|
package/package.json
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thatcher",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
4
4
|
"description": "A config-driven application framework for building data-intensive web apps without code.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"_exportsCuratedNote": "This map is intentionally curated, not a blanket ./lib/* + ./ui/* re-export of every internal file. Rationale (2026-07): grepping thatcher's own source found zero internal self-imports via the 'thatcher/lib/*' or 'thatcher/ui/*' package specifier (internal code uses relative paths / resolveModule file URLs instead), and grepping casey (the primary real external consumer, at ../casey) found it imports only the package root ('thatcher' -> createThatcher). README.md documents exactly two public entry shapes: the root ('thatcher') and 'thatcher/adapters/google-drive'. './engine.server' (auth) was already a named, deliberate entry point distinct from the internal lib dump. './config/*', './services/*', './validation/*', './plugins/*' are kept even though no consumer was evidenced, because they are small, purposeful, plausibly-public directories (plugin-authoring in particular mirrors casey's own plugins/case-tools pattern) and erring toward NOT breaking an unseen consumer outweighs the surface-area savings of dropping them. The wide-open './lib/*' and './ui/*' globs (70+ and 40+ internal implementation files respectively, covering error handling, rendering internals, busybase adapters, etc.) were removed because nothing -- internal or external -- was found to reference them via the package-specifier form; any of thatcher's own modules that genuinely need to reach another lib file already do so via a relative import, which this map does not gate. If a real external consumer is later found needing a specific lib/ui file, add that ONE subpath explicitly rather than reopening the blanket glob.",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": "./src/index.js",
|
|
9
10
|
"./engine.server": "./src/engine.server.js",
|
|
10
|
-
"./lib/*": "./src/lib/*.js",
|
|
11
|
-
"./lib/*.js": "./src/lib/*.js",
|
|
12
|
-
"./ui/*": "./src/ui/*.js",
|
|
13
|
-
"./ui/*.js": "./src/ui/*.js",
|
|
14
11
|
"./config/*": "./src/config/*.js",
|
|
15
12
|
"./config/*.js": "./src/config/*.js",
|
|
16
13
|
"./services/*": "./src/services/*.js",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NextResponse } from '@/lib/next-
|
|
1
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
2
2
|
import { createLogger } from '@/lib/logger.js';
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[AuditDashboardAPI]');
|
|
@@ -6,7 +6,7 @@ import { getUser, setCurrentRequest } from '@/engine.server';
|
|
|
6
6
|
import {
|
|
7
7
|
getPermissionAuditTrail, getPermissionAuditStats, getPermissionAuditBreakdown,
|
|
8
8
|
getPermissionAuditByDateRange, searchPermissionAudit, getPermissionDiff,
|
|
9
|
-
} from '@/lib/busybase
|
|
9
|
+
} from '@/lib/busybase/audit-reads';
|
|
10
10
|
|
|
11
11
|
export async function GET(request) {
|
|
12
12
|
setCurrentRequest(request);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { NextResponse } from '@/lib/next-
|
|
1
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
2
2
|
import { requireAuth } from '@/lib/auth-middleware';
|
|
3
3
|
import { searchLogs, getLogStats, rotateLogsOlderThan } from '@/lib/audit-logger-enhanced';
|
|
4
|
-
import { withErrorHandler } from '@/lib/
|
|
4
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
5
5
|
|
|
6
6
|
export const GET = withErrorHandler(async (request) => {
|
|
7
7
|
const user = await requireAuth();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NextResponse, cookies } from '@/lib/next-
|
|
1
|
+
import { NextResponse, cookies } from '@/lib/next-shim';
|
|
2
2
|
import { createLogger } from '@/lib/logger.js';
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[AuditDetailAPI]');
|
|
5
5
|
import { lucia } from '@/engine.server';
|
|
6
|
-
import { getPermissionAuditById, getPermissionDiff } from '@/lib/busybase
|
|
6
|
+
import { getPermissionAuditById, getPermissionDiff } from '@/lib/busybase/audit-reads';
|
|
7
7
|
|
|
8
8
|
async function getUser() {
|
|
9
9
|
const sessionId = (await cookies()).get(lucia.sessionCookieName)?.value ?? null;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { NextResponse } from '@/lib/next-
|
|
1
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
2
2
|
import { createLogger } from '@/lib/logger.js';
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[AuditAPI]');
|
|
5
5
|
import { lucia } from '@/engine.server';
|
|
6
|
-
import { cookies } from '@/lib/next-
|
|
6
|
+
import { cookies } from '@/lib/next-shim';
|
|
7
7
|
import {
|
|
8
8
|
logPermissionChange, getPermissionAuditTrail, searchPermissionAudit,
|
|
9
9
|
getPermissionAuditByDateRange, exportPermissionAuditCSV,
|
|
10
|
-
} from '@/lib/busybase
|
|
10
|
+
} from '@/lib/busybase/audit-reads';
|
|
11
11
|
|
|
12
12
|
async function getUser() {
|
|
13
13
|
const sessionId = (await cookies()).get(lucia.sessionCookieName)?.value ?? null;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NextResponse } from '@/lib/next-
|
|
1
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
2
2
|
import { createLogger } from '@/lib/logger.js';
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[AuditStatsAPI]');
|
|
5
5
|
import { getUser, setCurrentRequest } from '@/engine.server';
|
|
6
|
-
import { getPermissionAuditStats, getPermissionAuditBreakdown } from '@/lib/busybase
|
|
6
|
+
import { getPermissionAuditStats, getPermissionAuditBreakdown } from '@/lib/busybase/audit-reads';
|
|
7
7
|
|
|
8
8
|
export async function GET(request) {
|
|
9
9
|
setCurrentRequest(request);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { requireAuth, requirePermission } from '@/lib/auth-middleware';
|
|
2
|
-
import { getAuditHistory, getActionStats, getUserStats } from '@/lib/busybase
|
|
2
|
+
import { getAuditHistory, getActionStats, getUserStats } from '@/lib/busybase/audit-reads';
|
|
3
3
|
import { getSpec } from '@/config/spec-helpers';
|
|
4
4
|
import { paginated, ok } from '@/lib/response-formatter';
|
|
5
|
-
import { withErrorHandler } from '@/lib/
|
|
6
|
-
import { AppError } from '@/lib/error-handler';
|
|
5
|
+
import { withErrorHandler, AppError } from '@/lib/errors';
|
|
7
6
|
import { HTTP } from '@/config/constants';
|
|
8
7
|
import { parse as parseQuery } from '@/lib/query-string-adapter';
|
|
9
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { NextResponse } from '@/lib/next-
|
|
1
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
2
2
|
import { requireAuth } from '@/lib/auth-middleware';
|
|
3
3
|
import { getLogStats } from '@/lib/audit-logger-enhanced';
|
|
4
|
-
import { withErrorHandler } from '@/lib/
|
|
4
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
5
5
|
|
|
6
6
|
export const GET = withErrorHandler(async (request) => {
|
|
7
7
|
const user = await requireAuth();
|
|
@@ -8,7 +8,7 @@ import { GOOGLE_APIS } from '@/config/constants';
|
|
|
8
8
|
import { config } from '@/config';
|
|
9
9
|
import { getConfigEngine } from '@/lib/config-generator-engine';
|
|
10
10
|
import { globalManager } from '@/lib/hot-reload/mutex';
|
|
11
|
-
import { NextResponse } from '@/lib/next-
|
|
11
|
+
import { NextResponse } from '@/lib/next-shim';
|
|
12
12
|
import {
|
|
13
13
|
validateOAuthProvider,
|
|
14
14
|
getOAuthCookie,
|
|
@@ -3,7 +3,7 @@ import { getBy, verifyPassword, migrate } from '@/engine';
|
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[Login]');
|
|
5
5
|
import { initializeSystemConfig } from '@/config/system-config-loader';
|
|
6
|
-
import { withErrorHandler } from '@/lib/
|
|
6
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
7
7
|
import { lucia } from '@/engine.server';
|
|
8
8
|
|
|
9
9
|
let initialized = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { setCurrentRequest as setEngineRequest, invalidateSession } from '@/engine.server';
|
|
2
|
-
import { setCurrentRequest, setCurrentResponse } from '@/lib/next-
|
|
2
|
+
import { setCurrentRequest, setCurrentResponse } from '@/lib/next-shim';
|
|
3
3
|
|
|
4
4
|
function buildLogoutHeaders(headerMap) {
|
|
5
5
|
const setCookies = headerMap.get('Set-Cookie');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getBy, list, update } from '@/engine';
|
|
2
2
|
import { lucia } from '@/engine.server';
|
|
3
3
|
import { now } from '@/lib/id-helpers';
|
|
4
|
-
import { withErrorHandler } from '@/lib/
|
|
4
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
5
5
|
import crypto from 'crypto';
|
|
6
6
|
|
|
7
7
|
export const POST = withErrorHandler(async (request) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getBy, hashPassword, list, create, update, remove } from '@/engine';
|
|
2
2
|
import { genId, now } from '@/lib/id-helpers';
|
|
3
|
-
import { withErrorHandler } from '@/lib/
|
|
3
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
4
4
|
import crypto from 'crypto';
|
|
5
5
|
|
|
6
6
|
export const POST = withErrorHandler(async (request) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { generateToken } from '@/lib/csrf-protection';
|
|
2
2
|
import { ok } from '@/lib/response-formatter';
|
|
3
|
-
import { withErrorHandler } from '@/lib/
|
|
3
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
4
4
|
|
|
5
5
|
export const GET = withErrorHandler(async (request) => {
|
|
6
6
|
const token = generateToken();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { tracer } from '@/lib/tracing.js';
|
|
2
|
-
import { perfProfiler } from '@/lib/perf
|
|
2
|
+
import { perfProfiler } from '@/lib/perf.js';
|
|
3
3
|
import { debugRegistry } from '@/lib/debug-registry.js';
|
|
4
4
|
import { getExportSink } from '@/lib/export-sink.js';
|
|
5
5
|
import { getXStateWorkflowEngine } from '@/lib/xstate-workflow-engine.js';
|
|
6
6
|
import { getHyperFormulaService } from '@/lib/hyperformula-service.js';
|
|
7
|
-
import { getBusyBaseAdapter } from '@/lib/busybase
|
|
7
|
+
import { getBusyBaseAdapter } from '@/lib/busybase/adapter.js';
|
|
8
8
|
import { hookEngine } from '@/lib/hook-engine.js';
|
|
9
9
|
import { createLogger } from '@/lib/logger.js';
|
|
10
10
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { getDomainLoader } from '@/lib/domain-loader';
|
|
2
2
|
import { getConfigEngine } from '@/lib/config-generator-engine';
|
|
3
3
|
import { ok } from '@/lib/response-formatter';
|
|
4
|
-
import { withErrorHandler } from '@/lib/
|
|
5
|
-
import { AppError, NotFoundError } from '@/lib/error-handler';
|
|
4
|
+
import { withErrorHandler, AppError, NotFoundError } from '@/lib/errors';
|
|
6
5
|
import { HTTP } from '@/config/constants';
|
|
7
6
|
|
|
8
7
|
export const GET = withErrorHandler(async (request, context) => {
|
|
@@ -3,7 +3,7 @@ import { getDomainLoader } from '@/lib/domain-loader';
|
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[DomainsAPI]');
|
|
5
5
|
import { ok } from '@/lib/response-formatter';
|
|
6
|
-
import { withErrorHandler } from '@/lib/
|
|
6
|
+
import { withErrorHandler } from '@/lib/errors';
|
|
7
7
|
import { getConfigEngine } from '@/lib/config-generator-engine';
|
|
8
8
|
|
|
9
9
|
export const GET = withErrorHandler(async (request) => {
|
|
@@ -5,8 +5,7 @@ const log = createLogger('[Health]');
|
|
|
5
5
|
import path from 'path'
|
|
6
6
|
import { count } from '@/engine'
|
|
7
7
|
import { getAllMetrics } from '@/lib/metrics-collector.js'
|
|
8
|
-
import { getDatabaseStats } from '@/lib/
|
|
9
|
-
import { getCurrentResources } from '@/lib/resource-monitor.js'
|
|
8
|
+
import { getDatabaseStats, getCurrentResources } from '@/lib/monitor.js'
|
|
10
9
|
import { getRecentAlerts } from '@/lib/alert-manager.js'
|
|
11
10
|
|
|
12
11
|
function getLastSyncAt() {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getAllMetrics, clearMetrics } from '@/lib/metrics-collector.js'
|
|
2
2
|
import { getRecentAlerts } from '@/lib/alert-manager.js'
|
|
3
|
-
import { getDatabaseStats } from '@/lib/
|
|
4
|
-
import { getCurrentResources } from '@/lib/resource-monitor.js'
|
|
3
|
+
import { getDatabaseStats, getCurrentResources } from '@/lib/monitor.js'
|
|
5
4
|
import { getLogs } from '@/lib/log-aggregator.js'
|
|
6
5
|
|
|
7
6
|
export const GET = async (request) => {
|
package/src/engine.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Previously `@/engine` resolved to a non-existent module; this barrel makes it
|
|
2
|
-
// concrete and points the data layer at busybase
|
|
2
|
+
// concrete and points the data layer at busybase/store.
|
|
3
3
|
|
|
4
4
|
// Data layer (busybase)
|
|
5
5
|
export {
|
|
6
6
|
list, get, getBy, count, listWithPagination, searchWithPagination, search,
|
|
7
7
|
create, update, remove, bulkCreate, getChildren, batchGetChildren,
|
|
8
8
|
setBusyBaseClient,
|
|
9
|
-
} from '@/lib/busybase
|
|
9
|
+
} from '@/lib/busybase/store.js';
|
|
10
10
|
|
|
11
11
|
// IDs / time
|
|
12
12
|
export { genId, now } from '@/lib/id-helpers.js';
|
|
@@ -15,7 +15,7 @@ export { genId, now } from '@/lib/id-helpers.js';
|
|
|
15
15
|
export { hashPassword, verifyPassword } from '@/engine.server.js';
|
|
16
16
|
|
|
17
17
|
// Audit
|
|
18
|
-
export { logAction } from '@/lib/busybase
|
|
18
|
+
export { logAction } from '@/lib/busybase/audit.js';
|
|
19
19
|
|
|
20
20
|
// Legacy SQLite shims (data layer is busybase now). busybase is schemaless so there
|
|
21
21
|
// is no migration step; migrate() is a no-op kept for callers that still invoke it.
|
package/src/engine.server.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Lucia } from 'lucia';
|
|
3
3
|
import { Google } from 'arctic';
|
|
4
4
|
import bcrypt from 'bcrypt';
|
|
5
|
-
import { BusyBaseLuciaAdapter } from './lib/busybase
|
|
5
|
+
import { BusyBaseLuciaAdapter } from './lib/busybase/lucia-adapter.js';
|
|
6
6
|
import { buildConfig, hasGoogleAuth } from './config/env.js';
|
|
7
7
|
|
|
8
8
|
let _lucia = null;
|
|
@@ -118,13 +118,13 @@ export async function verifyPassword(password, hash) {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
export async function getUserByEmail(email) {
|
|
121
|
-
const { getBy } = await import('./lib/busybase
|
|
121
|
+
const { getBy } = await import('./lib/busybase/store.js');
|
|
122
122
|
return getBy('user', 'email', email);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export async function createUser(userData) {
|
|
126
126
|
const hashedPassword = await hashPassword(userData.password);
|
|
127
|
-
const { create } = await import('./lib/busybase
|
|
127
|
+
const { create } = await import('./lib/busybase/store.js');
|
|
128
128
|
return create('user', {
|
|
129
129
|
...userData,
|
|
130
130
|
password: hashedPassword,
|
package/src/index.js
CHANGED
|
@@ -141,9 +141,9 @@ export class Thatcher {
|
|
|
141
141
|
|| 'busybase_data';
|
|
142
142
|
const client = await createEmbedded({ dir });
|
|
143
143
|
|
|
144
|
-
const store = await import(resolveModule('./lib/busybase
|
|
144
|
+
const store = await import(resolveModule('./lib/busybase/store.js'));
|
|
145
145
|
store.setBusyBaseClient(client);
|
|
146
|
-
const audit = await import(resolveModule('./lib/busybase
|
|
146
|
+
const audit = await import(resolveModule('./lib/busybase/audit.js'));
|
|
147
147
|
audit.setBusyBaseClient(client);
|
|
148
148
|
|
|
149
149
|
this.busybase = client;
|
|
@@ -270,38 +270,38 @@ export class Thatcher {
|
|
|
270
270
|
// === CRUD operations ===
|
|
271
271
|
|
|
272
272
|
async list(entity, where = {}, opts = {}) {
|
|
273
|
-
const { list } = await import(resolveModule('./lib/busybase
|
|
273
|
+
const { list } = await import(resolveModule('./lib/busybase/store.js'));
|
|
274
274
|
return list(entity, where, opts);
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
async get(entity, id) {
|
|
278
|
-
const { get } = await import(resolveModule('./lib/busybase
|
|
278
|
+
const { get } = await import(resolveModule('./lib/busybase/store.js'));
|
|
279
279
|
return get(entity, id);
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
async create(entity, data, user) {
|
|
283
|
-
const { create } = await import(resolveModule('./lib/busybase
|
|
283
|
+
const { create } = await import(resolveModule('./lib/busybase/store.js'));
|
|
284
284
|
return create(entity, data, user);
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
// opts.expectedVersion: optional optimistic-concurrency guard (see
|
|
288
|
-
// busybase
|
|
288
|
+
// busybase/store.js update()) -- a caller that read the row's _version can
|
|
289
289
|
// pass it here to detect (via a thrown {code:'conflict'} error) a concurrent
|
|
290
290
|
// writer landing in between, instead of silently clobbering it. `user` stays
|
|
291
291
|
// its own positional param (unused by the store today, kept for API
|
|
292
292
|
// stability with existing callers); opts is a new, optional 5th param.
|
|
293
293
|
async update(entity, id, data, user, opts = {}) {
|
|
294
|
-
const { update } = await import(resolveModule('./lib/busybase
|
|
294
|
+
const { update } = await import(resolveModule('./lib/busybase/store.js'));
|
|
295
295
|
return update(entity, id, data, opts);
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
async delete(entity, id) {
|
|
299
|
-
const { remove } = await import(resolveModule('./lib/busybase
|
|
299
|
+
const { remove } = await import(resolveModule('./lib/busybase/store.js'));
|
|
300
300
|
return remove(entity, id);
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
async search(entity, query, where = {}, opts = {}) {
|
|
304
|
-
const { search } = await import(resolveModule('./lib/busybase
|
|
304
|
+
const { search } = await import(resolveModule('./lib/busybase/store.js'));
|
|
305
305
|
return search(entity, query, where, opts);
|
|
306
306
|
}
|
|
307
307
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { create, update, remove } from '@/engine';
|
|
4
4
|
import { requireUser, check } from '@/engine.server';
|
|
5
5
|
import { getSpec } from '@/config/spec-helpers';
|
|
6
|
-
import { revalidatePath } from '@/lib/next-
|
|
6
|
+
import { revalidatePath } from '@/lib/next-shim';
|
|
7
7
|
|
|
8
8
|
export async function serverCreateEntity(entityName, data) {
|
|
9
9
|
const user = await requireUser();
|
package/src/lib/api-helpers.js
CHANGED
package/src/lib/api.js
CHANGED
|
@@ -2,13 +2,12 @@ import { getUser } from '@/engine.server';
|
|
|
2
2
|
import { getSpec } from '@/config/spec-helpers';
|
|
3
3
|
import { API_ENDPOINTS } from '@/config';
|
|
4
4
|
import { can } from '@/services/permission.service';
|
|
5
|
-
import { get, create, update, remove, listWithPagination, search } from '@/lib/busybase
|
|
6
|
-
import { validateEntity, validateUpdate, hasErrors } from '@/lib/
|
|
5
|
+
import { get, create, update, remove, listWithPagination, search } from '@/lib/busybase/store';
|
|
6
|
+
import { validateEntity, validateUpdate, hasErrors } from '@/lib/validation/entity-validators';
|
|
7
7
|
import { broadcastUpdate } from '@/lib/realtime-server';
|
|
8
|
-
import { UnauthorizedError, PermissionError, NotFoundError, ValidationError, AppError } from '@/lib/
|
|
8
|
+
import { UnauthorizedError, PermissionError, NotFoundError, ValidationError, AppError, withErrorHandler } from '@/lib/errors';
|
|
9
9
|
import { ok, created, paginated } from '@/lib/response-formatter';
|
|
10
10
|
import { QueryAdapter } from '@/lib/query-string-adapter';
|
|
11
|
-
import { withErrorHandler } from '@/lib/with-error-handler';
|
|
12
11
|
import { HTTP } from '@/config/constants';
|
|
13
12
|
|
|
14
13
|
const createHandler = (entity, action) => async (request, { params, searchParams }) => {
|
|
@@ -2,7 +2,7 @@ import { createLogger } from './logger.js';
|
|
|
2
2
|
import { genId, now } from '@/lib/id-helpers';
|
|
3
3
|
|
|
4
4
|
const log = createLogger('[AuditEnhanced]');
|
|
5
|
-
import { list, create, remove } from '@/lib/busybase
|
|
5
|
+
import { list, create, remove } from '@/lib/busybase/store';
|
|
6
6
|
|
|
7
7
|
export const LOG_LEVELS = { DEBUG: 'debug', INFO: 'info', WARN: 'warn', ERROR: 'error' };
|
|
8
8
|
export const OPERATION_TYPES = { CREATE: 'create', UPDATE: 'update', DELETE: 'delete', READ: 'read', AUTH: 'auth', AUTHZ: 'authz' };
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { getUser, getLucia } from '../engine.server.js';
|
|
4
4
|
import { getSpec } from '../config/spec-helpers.js';
|
|
5
5
|
import { can } from '../services/permission.service.js';
|
|
6
|
-
import { UnauthorizedError, PermissionError, NotFoundError } from './
|
|
6
|
+
import { UnauthorizedError, PermissionError, NotFoundError } from './errors/index.js';
|
|
7
7
|
|
|
8
8
|
const actionMap = {
|
|
9
9
|
list: 'list',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createLogger } from '
|
|
2
|
-
import { hookEngine } from '
|
|
1
|
+
import { createLogger } from '../logger.js';
|
|
2
|
+
import { hookEngine } from '../hook-engine.js';
|
|
3
3
|
|
|
4
4
|
const logger = createLogger('[BusyBase]');
|
|
5
5
|
|
|
@@ -154,4 +154,4 @@ export function isBusyBaseAvailable() {
|
|
|
154
154
|
return _bbInstance?.initialized === true;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
export default BusyBaseAdapter;
|
|
157
|
+
export default BusyBaseAdapter;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* audit_logs and permission_audit tables.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { list, create } from '@/lib/busybase
|
|
7
|
+
import { list, create } from '@/lib/busybase/store.js';
|
|
8
8
|
import { genId, now } from '@/lib/id-helpers.js';
|
|
9
9
|
|
|
10
10
|
const parseJson = (val) => { try { return val ? JSON.parse(val) : null; } catch { return null; } };
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* forget: it returns immediately and swallows/logs write errors rather than throwing.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { createLogger } from '
|
|
10
|
-
import { genId, now } from '
|
|
9
|
+
import { createLogger } from '../logger.js';
|
|
10
|
+
import { genId, now } from '../id-helpers.js';
|
|
11
11
|
|
|
12
12
|
const log = createLogger('[BusyBaseAudit]');
|
|
13
13
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* receives back; busybase stores it as an epoch-ms number, so we convert at the boundary.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { list, get, create, update, remove } from '@/lib/busybase
|
|
10
|
+
import { list, get, create, update, remove } from '@/lib/busybase/store.js';
|
|
11
11
|
|
|
12
12
|
const SESSION = 'sessions';
|
|
13
13
|
const USER = 'users';
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
* Requires Bun (busybase embedded uses Bun.password + the vectordb native binding).
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { getSpec } from '
|
|
18
|
-
import { RECORD_STATUS } from '
|
|
19
|
-
import { genId, now } from '
|
|
17
|
+
import { getSpec } from '../../config/spec-helpers.js';
|
|
18
|
+
import { RECORD_STATUS } from '../../config/constants.js';
|
|
19
|
+
import { genId, now } from '../id-helpers.js';
|
|
20
20
|
|
|
21
21
|
let _client = null;
|
|
22
22
|
|