covara 0.7.0 → 0.8.0
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 +98 -62
- package/dist/cli/args.d.ts +14 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +78 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands/data.d.ts +2 -0
- package/dist/cli/commands/data.d.ts.map +1 -0
- package/dist/cli/commands/data.js +31 -0
- package/dist/cli/commands/data.js.map +1 -0
- package/dist/cli/commands/db.d.ts +2 -0
- package/dist/cli/commands/db.d.ts.map +1 -0
- package/dist/cli/commands/db.js +100 -0
- package/dist/cli/commands/db.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +2 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +125 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/env.d.ts +2 -0
- package/dist/cli/commands/env.d.ts.map +1 -0
- package/dist/cli/commands/env.js +94 -0
- package/dist/cli/commands/env.js.map +1 -0
- package/dist/cli/commands/import-export.d.ts +3 -0
- package/dist/cli/commands/import-export.d.ts.map +1 -0
- package/dist/cli/commands/import-export.js +156 -0
- package/dist/cli/commands/import-export.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +2 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +12 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/push.d.ts +2 -0
- package/dist/cli/commands/push.d.ts.map +1 -0
- package/dist/cli/commands/push.js +45 -0
- package/dist/cli/commands/push.js.map +1 -0
- package/dist/cli/commands/run.d.ts +2 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +54 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/seed.d.ts +2 -0
- package/dist/cli/commands/seed.d.ts.map +1 -0
- package/dist/cli/commands/seed.js +32 -0
- package/dist/cli/commands/seed.js.map +1 -0
- package/dist/cli/commands/studio.d.ts +2 -0
- package/dist/cli/commands/studio.d.ts.map +1 -0
- package/dist/cli/commands/studio.js +22 -0
- package/dist/cli/commands/studio.js.map +1 -0
- package/dist/cli/commands/types.d.ts +2 -0
- package/dist/cli/commands/types.d.ts.map +1 -0
- package/dist/cli/commands/types.js +28 -0
- package/dist/cli/commands/types.js.map +1 -0
- package/dist/cli/config.d.ts +28 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +81 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/drizzle-bridge.d.ts +29 -0
- package/dist/cli/drizzle-bridge.d.ts.map +1 -0
- package/dist/cli/drizzle-bridge.js +85 -0
- package/dist/cli/drizzle-bridge.js.map +1 -0
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +74 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/prompt.d.ts +2 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +16 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/templates/package-json.js +1 -1
- package/dist/cli/worker.d.ts +2 -0
- package/dist/cli/worker.d.ts.map +1 -0
- package/dist/cli/worker.js +120 -0
- package/dist/cli/worker.js.map +1 -0
- package/dist/client/file-upload.d.ts +2 -1
- package/dist/client/file-upload.d.ts.map +1 -1
- package/dist/client/file-upload.js +5 -5
- package/dist/client/file-upload.js.map +1 -1
- package/dist/client/live-store.d.ts.map +1 -1
- package/dist/client/live-store.js +12 -6
- package/dist/client/live-store.js.map +1 -1
- package/dist/client/react-files.js +1 -1
- package/dist/client/react-files.js.map +1 -1
- package/dist/client/subscription-manager.d.ts.map +1 -1
- package/dist/client/subscription-manager.js +7 -0
- package/dist/client/subscription-manager.js.map +1 -1
- package/dist/htmx/client/runtime.d.ts +2 -0
- package/dist/htmx/client/runtime.d.ts.map +1 -0
- package/dist/htmx/client/runtime.js +195 -0
- package/dist/htmx/client/runtime.js.map +1 -0
- package/dist/htmx/context.d.ts +16 -0
- package/dist/htmx/context.d.ts.map +1 -0
- package/dist/htmx/context.js +52 -0
- package/dist/htmx/context.js.map +1 -0
- package/dist/htmx/forms.d.ts +3 -0
- package/dist/htmx/forms.d.ts.map +1 -0
- package/dist/htmx/forms.js +32 -0
- package/dist/htmx/forms.js.map +1 -0
- package/dist/htmx/ids.d.ts +11 -0
- package/dist/htmx/ids.d.ts.map +1 -0
- package/dist/htmx/ids.js +27 -0
- package/dist/htmx/ids.js.map +1 -0
- package/dist/htmx/index.d.ts +11 -0
- package/dist/htmx/index.d.ts.map +1 -0
- package/dist/htmx/index.js +15 -0
- package/dist/htmx/index.js.map +1 -0
- package/dist/htmx/live.d.ts +39 -0
- package/dist/htmx/live.d.ts.map +1 -0
- package/dist/htmx/live.js +37 -0
- package/dist/htmx/live.js.map +1 -0
- package/dist/htmx/page.d.ts +14 -0
- package/dist/htmx/page.d.ts.map +1 -0
- package/dist/htmx/page.js +59 -0
- package/dist/htmx/page.js.map +1 -0
- package/dist/htmx/render-util.d.ts +2 -0
- package/dist/htmx/render-util.d.ts.map +1 -0
- package/dist/htmx/render-util.js +15 -0
- package/dist/htmx/render-util.js.map +1 -0
- package/dist/htmx/server.d.ts +21 -0
- package/dist/htmx/server.d.ts.map +1 -0
- package/dist/htmx/server.js +286 -0
- package/dist/htmx/server.js.map +1 -0
- package/dist/htmx/sse-render.d.ts +10 -0
- package/dist/htmx/sse-render.d.ts.map +1 -0
- package/dist/htmx/sse-render.js +40 -0
- package/dist/htmx/sse-render.js.map +1 -0
- package/dist/htmx/template-gen.d.ts +7 -0
- package/dist/htmx/template-gen.d.ts.map +1 -0
- package/dist/htmx/template-gen.js +38 -0
- package/dist/htmx/template-gen.js.map +1 -0
- package/dist/resource/hook.d.ts.map +1 -1
- package/dist/resource/hook.js +101 -24
- package/dist/resource/hook.js.map +1 -1
- package/dist/resource/relations.d.ts +15 -4
- package/dist/resource/relations.d.ts.map +1 -1
- package/dist/resource/relations.js +146 -26
- package/dist/resource/relations.js.map +1 -1
- package/dist/resource/subscription.d.ts +15 -2
- package/dist/resource/subscription.d.ts.map +1 -1
- package/dist/resource/subscription.js +184 -3
- package/dist/resource/subscription.js.map +1 -1
- package/dist/resource/track-mutations.d.ts.map +1 -1
- package/dist/resource/track-mutations.js +11 -1
- package/dist/resource/track-mutations.js.map +1 -1
- package/dist/resource/types.d.ts +8 -0
- package/dist/resource/types.d.ts.map +1 -1
- package/dist/server/admin-bypass.d.ts +7 -0
- package/dist/server/admin-bypass.d.ts.map +1 -0
- package/dist/server/admin-bypass.js +22 -0
- package/dist/server/admin-bypass.js.map +1 -0
- package/dist/server/app.d.ts +9 -0
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +101 -1
- package/dist/server/app.js.map +1 -1
- package/dist/server/impersonation.d.ts +18 -0
- package/dist/server/impersonation.d.ts.map +1 -0
- package/dist/server/impersonation.js +53 -0
- package/dist/server/impersonation.js.map +1 -0
- package/dist/shared/escape.d.ts +3 -0
- package/dist/shared/escape.d.ts.map +1 -0
- package/dist/shared/escape.js +12 -0
- package/dist/shared/escape.js.map +1 -0
- package/dist/storage/local.d.ts +4 -0
- package/dist/storage/local.d.ts.map +1 -1
- package/dist/storage/local.js +5 -0
- package/dist/storage/local.js.map +1 -1
- package/dist/storage/resource.d.ts +5 -11
- package/dist/storage/resource.d.ts.map +1 -1
- package/dist/storage/resource.js +156 -194
- package/dist/storage/resource.js.map +1 -1
- package/dist/ui/admin-auth.d.ts +6 -0
- package/dist/ui/admin-auth.d.ts.map +1 -1
- package/dist/ui/admin-auth.js +59 -1
- package/dist/ui/admin-auth.js.map +1 -1
- package/dist/ui/data-explorer.d.ts.map +1 -1
- package/dist/ui/data-explorer.js +91 -4
- package/dist/ui/data-explorer.js.map +1 -1
- package/dist/ui/html/client/data-explorer-app.d.ts.map +1 -1
- package/dist/ui/html/client/data-explorer-app.js +20 -7
- package/dist/ui/html/client/data-explorer-app.js.map +1 -1
- package/dist/ui/html/client/runtime.d.ts.map +1 -1
- package/dist/ui/html/client/runtime.js +70 -2
- package/dist/ui/html/client/runtime.js.map +1 -1
- package/dist/ui/html/icons.d.ts.map +1 -1
- package/dist/ui/html/icons.js +2 -0
- package/dist/ui/html/icons.js.map +1 -1
- package/dist/ui/html/layout.d.ts +1 -0
- package/dist/ui/html/layout.d.ts.map +1 -1
- package/dist/ui/html/layout.js +274 -146
- package/dist/ui/html/layout.js.map +1 -1
- package/dist/ui/html/pages/filter-tester.d.ts.map +1 -1
- package/dist/ui/html/pages/filter-tester.js +15 -0
- package/dist/ui/html/pages/filter-tester.js.map +1 -1
- package/dist/ui/html/pages/users.d.ts.map +1 -1
- package/dist/ui/html/pages/users.js +8 -1
- package/dist/ui/html/pages/users.js.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/middleware.d.ts.map +1 -1
- package/dist/ui/middleware.js +121 -5
- package/dist/ui/middleware.js.map +1 -1
- package/dist/ui/schema-registry.d.ts +5 -0
- package/dist/ui/schema-registry.d.ts.map +1 -1
- package/dist/ui/schema-registry.js +14 -0
- package/dist/ui/schema-registry.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Covara</h1>
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>📚 <a href="https://kahveciderin.github.io/covara">Documentation</a></strong>
|
|
9
|
+
·
|
|
10
|
+
<a href="https://kahveciderin.github.io/covara/quick-start">Quick Start</a>
|
|
11
|
+
·
|
|
12
|
+
<a href="https://kahveciderin.github.io/covara/tutorial">Tutorial</a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
7
15
|
**Your Drizzle schema is already a backend.** Covara turns it into a complete, production-ready API — REST endpoints, real-time subscriptions, auth, file uploads, billing, email, and background jobs — with a type-safe, offline-first TypeScript client on the other end. Built on [Hono](https://hono.dev), it runs standalone on Node or at the edge on Cloudflare Workers.
|
|
8
16
|
|
|
9
17
|
## The Goal
|
|
@@ -44,7 +52,7 @@ function TodoList() {
|
|
|
44
52
|
### Core API
|
|
45
53
|
- **Automatic REST API** - Full CRUD endpoints from your Drizzle schema
|
|
46
54
|
- **Real-time Subscriptions** - SSE with changelog-based updates, sequence numbers, and seamless reconnection
|
|
47
|
-
- **Relations & Joins** - `belongsTo`, `hasOne`, `hasMany`, `manyToMany` with efficient batch loading
|
|
55
|
+
- **Relations & Joins** - `belongsTo`, `hasOne`, `hasMany`, `manyToMany` with efficient batch loading, optional foreign-key **auto-discovery** (`autoRelations`), and **scope-enforced includes** (a relation never reveals rows the user couldn't read directly)
|
|
48
56
|
- **RSQL Filtering** - Comprehensive query language (30+ operators) plus custom operators
|
|
49
57
|
- **Cursor Pagination** - Keyset pagination with multi-field ordering
|
|
50
58
|
- **Aggregations** - Group by, count, sum, avg, min, max, with `HAVING` filtering on aggregate output — available as a one-shot query or a live subscription (`useLiveAggregate`) that recomputes on every change
|
|
@@ -82,7 +90,8 @@ function TodoList() {
|
|
|
82
90
|
|
|
83
91
|
### File Storage
|
|
84
92
|
- **Storage Adapters** - Local disk, S3, Cloudflare R2 (native binding or S3-compat), and in-memory behind one `StorageAdapter` interface
|
|
85
|
-
- **File Resources** -
|
|
93
|
+
- **File Resources** - First-class resources with an upload/download layer: `app.fileResource(...)` chains like any resource and inherits the full CRUD/hooks/procedures/relations/subscriptions/scopes surface, plus MIME/size validation, per-user keys, and storage cleanup on delete
|
|
94
|
+
- **Zero-config local serving** - `createCovara` auto-serves a local adapter's `baseUrl` (no manual `serveStatic`); admin data explorer gets a per-row Download action
|
|
86
95
|
- **Presigned URLs** - Optional direct-to-bucket uploads/downloads with configurable expiry
|
|
87
96
|
- **React Hooks** - `useFileUpload` (with progress), `useFile`, `useFiles`; `getDownloadUrl()` for React Native
|
|
88
97
|
|
|
@@ -117,6 +126,13 @@ function TodoList() {
|
|
|
117
126
|
- **Auth Strategies** - OIDC (PKCE flow, token refresh), JWT, bearer, API key, or cookie sessions — selected per client or auto-detected
|
|
118
127
|
- **HMR-safe** - `getOrCreateClient` for development
|
|
119
128
|
|
|
129
|
+
### Server-rendered htmx (Beta)
|
|
130
|
+
- **One JSX page → full app** - `app.page(path, Component)` server-renders a page whose `<Live>` regions auto-generate the htmx endpoints (list/create/update/delete/subscribe). Covara generates wiring, not UI components
|
|
131
|
+
- **Live by default** - each region streams server-rendered fragments over SSE (reusing the existing subscription engine); rows update in place as anyone mutates the resource
|
|
132
|
+
- **Optimistic & offline** - new rows insert once via the live SSE (no duplicate/phantom), deletes are optimistic, and mutations queue offline and replay on reconnect
|
|
133
|
+
- **No client framework** - vendored htmx core + a tiny runtime, served and injected automatically
|
|
134
|
+
- **Beta** - newer than the JSON API + TypeScript client; the API may still change
|
|
135
|
+
|
|
120
136
|
### Environment Variables
|
|
121
137
|
- **Type-safe Configuration** - Define and validate env vars with Zod via `createEnv` / `envVariable`
|
|
122
138
|
- **Public and Private Vars** - `PUBLIC_`-prefixed or explicitly-marked vars served to clients via `usePublicEnv` (with ETag)
|
|
@@ -124,6 +140,7 @@ function TodoList() {
|
|
|
124
140
|
|
|
125
141
|
### Developer Experience
|
|
126
142
|
- **Project Scaffolding** - `npx covara create my-app` (Node/Workers templates, SQLite/Postgres), plus `covara generate resource|migration`
|
|
143
|
+
- **`covara dev` Loop** - Dev watcher: streams schema changes to the DB (additive auto-applied, destructive gated), regenerates the typed client, runs the server — no manual push. Plus `covara db` connection profiles (local/remote/Turso/Postgres), `push`/`migrate`/`studio`, and `data`/`import`/`export`/`run`/`types`
|
|
127
144
|
- **Deploy-Ready Output** - Generated Dockerfile, docker-compose, complete wrangler.toml, GitHub Actions CI, `.env.example`
|
|
128
145
|
- **Framework Migrations** - `covara/db` ships canonical internal-table schemas, an idempotent `autoMigrate`/`migrateInternal`, a generic seeder, and pool-sizing helpers
|
|
129
146
|
- **App Factory** - `createCovara()` wires errors, auth, security headers, health, OpenAPI, admin UI
|
|
@@ -214,7 +231,7 @@ database_name = "my-app"
|
|
|
214
231
|
|
|
215
232
|
Workers bill CPU time, not wall-clock time — long-lived idle SSE subscriptions cost almost nothing, since heartbeats and event pushes use negligible CPU.
|
|
216
233
|
|
|
217
|
-
For production Workers deployments, bind the bundled `CovaraKVDurableObject` as Covara's KV store so subscriptions, rate limits, and sessions are shared across isolates — see [
|
|
234
|
+
For production Workers deployments, bind the bundled `CovaraKVDurableObject` as Covara's KV store so subscriptions, rate limits, and sessions are shared across isolates — see the [Durable Object KV guide](https://kahveciderin.github.io/covara/deployment/durable-object-kv). Projects scaffolded with `covara create --template cloudflare` have it wired up already.
|
|
218
235
|
|
|
219
236
|
### Using a plain Hono app
|
|
220
237
|
|
|
@@ -318,7 +335,7 @@ app.resource("/posts", postsTable, {
|
|
|
318
335
|
});
|
|
319
336
|
```
|
|
320
337
|
|
|
321
|
-
See [
|
|
338
|
+
See the [Resources reference](https://kahveciderin.github.io/covara/core/resources-and-app) for the full option reference (soft delete, computed fields, field allowlists, search, custom filter operators, and more).
|
|
322
339
|
|
|
323
340
|
## Client Library
|
|
324
341
|
|
|
@@ -428,30 +445,69 @@ const subscription = users.subscribe(
|
|
|
428
445
|
|
|
429
446
|
The client has no hard DOM dependencies: pass an AsyncStorage-backed `TokenStorage` for JWT auth, offline persistence picks an environment-appropriate backend, and the file hooks expose `getDownloadUrl()` for use with `Linking` instead of browser downloads.
|
|
430
447
|
|
|
448
|
+
## Server-rendered htmx (Beta)
|
|
449
|
+
|
|
450
|
+
> **Beta.** This is newer than the JSON API and TypeScript client and may still change between releases. The JSON API it builds on is stable.
|
|
451
|
+
|
|
452
|
+
Prefer hypermedia over a client framework? Register a single JSX page; `<Live>` is the only special element, and Covara generates the htmx endpoints, the live SSE stream, and the optimistic/offline client runtime for you.
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
// tsconfig: { "jsx": "react-jsx", "jsxImportSource": "hono/jsx" }
|
|
456
|
+
import { createCovara } from "covara/server";
|
|
457
|
+
import { Live } from "covara/htmx";
|
|
458
|
+
import { todos } from "./schema";
|
|
459
|
+
|
|
460
|
+
const app = createCovara()
|
|
461
|
+
.resource("/todos", todos, { id: todos.id, db })
|
|
462
|
+
.page("/todos", () => (
|
|
463
|
+
<Live
|
|
464
|
+
resource={todos}
|
|
465
|
+
query={{ orderBy: "position" }}
|
|
466
|
+
create={(c) => (
|
|
467
|
+
<form {...c.create()}>
|
|
468
|
+
<input name="title" />
|
|
469
|
+
<button>Add</button>
|
|
470
|
+
</form>
|
|
471
|
+
)}
|
|
472
|
+
container={(rows, c) => <ul {...c.container()}>{rows}</ul>}
|
|
473
|
+
render={(t, c) => (
|
|
474
|
+
<li {...c.row(t.id)}>
|
|
475
|
+
{t.title}
|
|
476
|
+
<button {...c.delete(t.id)}>Delete</button>
|
|
477
|
+
</li>
|
|
478
|
+
)}
|
|
479
|
+
/>
|
|
480
|
+
));
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
`GET /todos` is now a full server-rendered page. Creating a todo in one browser tab streams the new row into every other tab over SSE; updates and deletes patch rows in place. The helpers (`c.create()`, `c.row(id)`, `c.update(id)`, `c.delete(id)`, `c.container()`) emit plain htmx attributes pointing at auto-generated endpoints under `/__covara/live`. See the [htmx docs](https://kahveciderin.github.io/covara/htmx/overview) for optimistic/offline behavior, live aggregates, and scoping.
|
|
484
|
+
|
|
431
485
|
## File Storage
|
|
432
486
|
|
|
433
|
-
Configure a storage backend once, then
|
|
487
|
+
Configure a storage backend once, then chain a file resource like any other. Local uploads are auto-served at `baseUrl` — no `serveStatic` wiring:
|
|
434
488
|
|
|
435
489
|
```typescript
|
|
436
|
-
import {
|
|
490
|
+
import { createCovara, initializeStorage } from "covara";
|
|
437
491
|
|
|
438
492
|
initializeStorage({
|
|
439
493
|
type: "local", // or "s3" | "r2" | "memory"
|
|
440
494
|
local: { basePath: "./uploads", baseUrl: "/uploads" },
|
|
441
495
|
});
|
|
442
496
|
|
|
443
|
-
app
|
|
444
|
-
db
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
497
|
+
const app = createCovara({ cors: true })
|
|
498
|
+
.resource("/todos", todosTable, { id: todosTable.id, db })
|
|
499
|
+
.fileResource("/files", filesTable, {
|
|
500
|
+
db,
|
|
501
|
+
id: filesTable.id,
|
|
502
|
+
allowedMimeTypes: ["image/jpeg", "image/png"],
|
|
503
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
504
|
+
auth: {
|
|
505
|
+
read: async (user) => rsql`userId==${user?.id}`,
|
|
506
|
+
delete: async (user) => rsql`userId==${user?.id}`,
|
|
507
|
+
},
|
|
508
|
+
usePresignedUrls: true, // direct-to-bucket on S3/R2
|
|
509
|
+
// ...plus any resource option: hooks, relations, procedures, subscriptions
|
|
510
|
+
});
|
|
455
511
|
```
|
|
456
512
|
|
|
457
513
|
Upload from React with progress tracking:
|
|
@@ -475,7 +531,7 @@ function Uploader() {
|
|
|
475
531
|
}
|
|
476
532
|
```
|
|
477
533
|
|
|
478
|
-
See [
|
|
534
|
+
See [Storage](https://kahveciderin.github.io/covara/platform/storage).
|
|
479
535
|
|
|
480
536
|
## Server-side Authentication
|
|
481
537
|
|
|
@@ -494,7 +550,7 @@ app.route("/api/auth", router); // /me, /login, /signup, /logout
|
|
|
494
550
|
app.use("*", middleware); // populates c.get("user")
|
|
495
551
|
```
|
|
496
552
|
|
|
497
|
-
Opt-in extras: TOTP MFA with backup codes, magic links, email verification, password reset, login throttling, CSRF protection, and API key management. See [
|
|
553
|
+
Opt-in extras: TOTP MFA with backup codes, magic links, email verification, password reset, login throttling, CSRF protection, and API key management. See [Authentication](https://kahveciderin.github.io/covara/auth/overview).
|
|
498
554
|
|
|
499
555
|
### OIDC Provider
|
|
500
556
|
|
|
@@ -572,7 +628,7 @@ await getTaskScheduler().scheduleRecurring(dailyReportTask, {}, {
|
|
|
572
628
|
});
|
|
573
629
|
```
|
|
574
630
|
|
|
575
|
-
On Workers, swap the poller for the Cloudflare Queues adapter. See [
|
|
631
|
+
On Workers, swap the poller for the Cloudflare Queues adapter. See [Background tasks](https://kahveciderin.github.io/covara/platform/tasks).
|
|
576
632
|
|
|
577
633
|
## Email
|
|
578
634
|
|
|
@@ -592,7 +648,7 @@ const { html, text } = createEmail({ brandColor: "#4f46e5" })
|
|
|
592
648
|
await sendEmail({ from: "noreply@acme.com", to: email, subject: "Verify your email", html, text });
|
|
593
649
|
```
|
|
594
650
|
|
|
595
|
-
The builder renders responsive, escaped HTML plus a plaintext fallback. A Cloudflare Email Service adapter is included for Workers. See [
|
|
651
|
+
The builder renders responsive, escaped HTML plus a plaintext fallback. A Cloudflare Email Service adapter is included for Workers. See [Email](https://kahveciderin.github.io/covara/platform/email).
|
|
596
652
|
|
|
597
653
|
## Billing
|
|
598
654
|
|
|
@@ -634,7 +690,7 @@ function Account() {
|
|
|
634
690
|
}
|
|
635
691
|
```
|
|
636
692
|
|
|
637
|
-
Webhooks are signature-verified, deduplicated, and grant credits automatically on `payment.succeeded`. See [
|
|
693
|
+
Webhooks are signature-verified, deduplicated, and grant credits automatically on `payment.succeeded`. See [Billing](https://kahveciderin.github.io/covara/platform/billing).
|
|
638
694
|
|
|
639
695
|
## Mutation Tracking
|
|
640
696
|
|
|
@@ -697,7 +753,7 @@ const env = createEnv({
|
|
|
697
753
|
app.route("/api/env", usePublicEnv(env)); // serves public vars (with ETag)
|
|
698
754
|
```
|
|
699
755
|
|
|
700
|
-
Clients read public vars with `fetchPublicEnv`/`createEnvClient` or the `usePublicEnv` React hook. See [
|
|
756
|
+
Clients read public vars with `fetchPublicEnv`/`createEnvClient` or the `usePublicEnv` React hook. See [Environment variables](https://kahveciderin.github.io/covara/deployment/environment-variables).
|
|
701
757
|
|
|
702
758
|
## Query Parameters
|
|
703
759
|
|
|
@@ -739,7 +795,7 @@ age=between=[18,65] # Range (inclusive)
|
|
|
739
795
|
deletedAt=isnull=true # Is null
|
|
740
796
|
bio=isempty=false # Has non-empty value
|
|
741
797
|
|
|
742
|
-
# See
|
|
798
|
+
# See https://kahveciderin.github.io/covara/core/filtering for all 30+ operators
|
|
743
799
|
```
|
|
744
800
|
|
|
745
801
|
The same expression filters database queries, subscription scopes, and auth scopes — parsed once, executed as SQL or in-memory as needed.
|
|
@@ -794,47 +850,27 @@ expect(res.status).toBe(201);
|
|
|
794
850
|
|
|
795
851
|
## Documentation
|
|
796
852
|
|
|
797
|
-
|
|
853
|
+
📚 **Full documentation: [kahveciderin.github.io/covara](https://kahveciderin.github.io/covara)**
|
|
798
854
|
|
|
799
|
-
|
|
800
|
-
- [Getting Started Guide](./wiki/getting-started.md) - Installation and quick start
|
|
801
|
-
- [Deployment](./wiki/deployment.md) - Node, Cloudflare Workers, database matrix
|
|
802
|
-
- [Migrating from Express](./wiki/migrating-from-express.md) - Upgrading from Covara ≤ 0.5
|
|
855
|
+
The docs site is built with Docusaurus from the [`website/`](./website) folder and published to GitHub Pages automatically (`.github/workflows/docs.yml`). Highlights:
|
|
803
856
|
|
|
804
|
-
|
|
805
|
-
- [Resources](
|
|
806
|
-
- [
|
|
807
|
-
- [
|
|
808
|
-
- [
|
|
809
|
-
- [
|
|
810
|
-
- [
|
|
811
|
-
- [
|
|
857
|
+
- **Get started** — [Introduction](https://kahveciderin.github.io/covara/), [Quick Start](https://kahveciderin.github.io/covara/quick-start), [Tutorial](https://kahveciderin.github.io/covara/tutorial)
|
|
858
|
+
- **Core** — [Resources](https://kahveciderin.github.io/covara/core/resources-and-app), [Filtering](https://kahveciderin.github.io/covara/core/filtering), [Pagination](https://kahveciderin.github.io/covara/core/pagination), [Aggregations](https://kahveciderin.github.io/covara/core/aggregations), [Relations](https://kahveciderin.github.io/covara/core/relations), [Search](https://kahveciderin.github.io/covara/core/search)
|
|
859
|
+
- **Real-time** — [Subscriptions](https://kahveciderin.github.io/covara/realtime/subscriptions), [Aggregate subscriptions](https://kahveciderin.github.io/covara/realtime/aggregate-subscriptions), [Mutation tracking](https://kahveciderin.github.io/covara/realtime/mutation-tracking)
|
|
860
|
+
- **Auth & security** — [Overview](https://kahveciderin.github.io/covara/auth/overview), [OIDC provider](https://kahveciderin.github.io/covara/auth/oidc-provider), [JWT](https://kahveciderin.github.io/covara/auth/jwt), [Scopes](https://kahveciderin.github.io/covara/auth/scopes)
|
|
861
|
+
- **Platform** — [Storage](https://kahveciderin.github.io/covara/platform/storage), [Email](https://kahveciderin.github.io/covara/platform/email), [Billing](https://kahveciderin.github.io/covara/platform/billing), [Tasks](https://kahveciderin.github.io/covara/platform/tasks), [KV](https://kahveciderin.github.io/covara/platform/kv)
|
|
862
|
+
- **Client** — [Overview](https://kahveciderin.github.io/covara/client/overview), [React hooks](https://kahveciderin.github.io/covara/client/react-hooks), [Offline](https://kahveciderin.github.io/covara/client/offline), [Type generation](https://kahveciderin.github.io/covara/client/typegen)
|
|
863
|
+
- **Deploy** — [Node](https://kahveciderin.github.io/covara/deployment/node), [Cloudflare Workers](https://kahveciderin.github.io/covara/deployment/workers), [Databases](https://kahveciderin.github.io/covara/deployment/databases)
|
|
864
|
+
- **Reference** — [Contracts (invariants)](https://kahveciderin.github.io/covara/contracts/overview), [Error handling](https://kahveciderin.github.io/covara/tooling/error-handling), [Migrating from Express](https://kahveciderin.github.io/covara/migration/from-express)
|
|
812
865
|
|
|
813
|
-
|
|
814
|
-
- [Subscriptions](./wiki/subscriptions.md) - SSE subscriptions and changelog
|
|
866
|
+
Run the docs locally:
|
|
815
867
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
- [Email](./wiki/email.md) - Email adapters and template builder
|
|
823
|
-
- [Billing](./wiki/billing.md) - Payment providers, plans, credits, webhooks
|
|
824
|
-
- [Tasks](./wiki/tasks.md) - Background job queue, scheduling, retries
|
|
825
|
-
- [Environment Variables](./wiki/environment-variables.md) - Typed env config
|
|
826
|
-
|
|
827
|
-
### Client
|
|
828
|
-
- [Client Library](./wiki/client-library.md) - TypeScript client with React hooks
|
|
829
|
-
- [Offline Support](./wiki/offline-support.md) - Offline-first capabilities
|
|
830
|
-
|
|
831
|
-
### Advanced
|
|
832
|
-
- [Procedures & Hooks](./wiki/procedures.md) - RPC and lifecycle hooks
|
|
833
|
-
- [Mutation Tracking](./wiki/track-mutations.md) - Automatic changelog and cache invalidation
|
|
834
|
-
- [Middleware](./wiki/middleware.md) - Observability, versioning, idempotency
|
|
835
|
-
- [OpenAPI](./wiki/openapi.md) - OpenAPI spec generation
|
|
836
|
-
- [Admin UI](./wiki/admin-ui.md) - Built-in dashboard
|
|
837
|
-
- [Error Handling](./wiki/error-handling.md) - Error types and handling
|
|
868
|
+
```bash
|
|
869
|
+
cd website
|
|
870
|
+
pnpm install
|
|
871
|
+
pnpm start # dev server with hot reload
|
|
872
|
+
pnpm build # production build (validates all internal links)
|
|
873
|
+
```
|
|
838
874
|
|
|
839
875
|
## Requirements
|
|
840
876
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ParsedArgs {
|
|
2
|
+
positionals: string[];
|
|
3
|
+
flags: Record<string, string | boolean>;
|
|
4
|
+
passthrough: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface ParseOptions {
|
|
7
|
+
booleans?: string[];
|
|
8
|
+
aliases?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export declare const parseArgs: (argv: string[], opts?: ParseOptions) => ParsedArgs;
|
|
11
|
+
export declare const getString: (parsed: ParsedArgs, name: string) => string | undefined;
|
|
12
|
+
export declare const getBool: (parsed: ParsedArgs, name: string) => boolean;
|
|
13
|
+
export declare const hasFlag: (parsed: ParsedArgs, name: string) => boolean;
|
|
14
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAQD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,EAAE,OAAM,YAAiB,KAAG,UA4DnE,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,QAAQ,UAAU,EAClB,MAAM,MAAM,KACX,MAAM,GAAG,SAGX,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAG,OAE1D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAG,OAE1D,CAAC"}
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const splitInline = (arg) => {
|
|
2
|
+
const eq = arg.indexOf("=");
|
|
3
|
+
if (eq === -1)
|
|
4
|
+
return [arg, undefined];
|
|
5
|
+
return [arg.slice(0, eq), arg.slice(eq + 1)];
|
|
6
|
+
};
|
|
7
|
+
export const parseArgs = (argv, opts = {}) => {
|
|
8
|
+
const booleans = new Set(opts.booleans ?? []);
|
|
9
|
+
const aliases = opts.aliases ?? {};
|
|
10
|
+
const positionals = [];
|
|
11
|
+
const flags = {};
|
|
12
|
+
const passthrough = [];
|
|
13
|
+
const rest = [...argv];
|
|
14
|
+
while (rest.length > 0) {
|
|
15
|
+
const arg = rest.shift();
|
|
16
|
+
if (arg === "--") {
|
|
17
|
+
passthrough.push(...rest);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
if (arg.startsWith("--")) {
|
|
21
|
+
const [rawName, inline] = splitInline(arg.slice(2));
|
|
22
|
+
if (rawName.startsWith("no-") && inline === undefined && !booleans.has(rawName)) {
|
|
23
|
+
flags[rawName.slice(3)] = false;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const name = aliases[rawName] ?? rawName;
|
|
27
|
+
if (inline !== undefined) {
|
|
28
|
+
flags[name] = inline;
|
|
29
|
+
}
|
|
30
|
+
else if (booleans.has(rawName) || booleans.has(name)) {
|
|
31
|
+
flags[name] = true;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const next = rest[0];
|
|
35
|
+
if (next === undefined || next.startsWith("-")) {
|
|
36
|
+
flags[name] = true;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
flags[name] = rest.shift();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (arg.startsWith("-") && arg.length > 1) {
|
|
45
|
+
const [rawName, inline] = splitInline(arg.slice(1));
|
|
46
|
+
const name = aliases[rawName] ?? rawName;
|
|
47
|
+
if (inline !== undefined) {
|
|
48
|
+
flags[name] = inline;
|
|
49
|
+
}
|
|
50
|
+
else if (booleans.has(rawName) || booleans.has(name)) {
|
|
51
|
+
flags[name] = true;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const next = rest[0];
|
|
55
|
+
if (next === undefined || next.startsWith("-")) {
|
|
56
|
+
flags[name] = true;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
flags[name] = rest.shift();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
positionals.push(arg);
|
|
65
|
+
}
|
|
66
|
+
return { positionals, flags, passthrough };
|
|
67
|
+
};
|
|
68
|
+
export const getString = (parsed, name) => {
|
|
69
|
+
const v = parsed.flags[name];
|
|
70
|
+
return typeof v === "string" ? v : undefined;
|
|
71
|
+
};
|
|
72
|
+
export const getBool = (parsed, name) => {
|
|
73
|
+
return parsed.flags[name] === true;
|
|
74
|
+
};
|
|
75
|
+
export const hasFlag = (parsed, name) => {
|
|
76
|
+
return name in parsed.flags;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/data.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAyBhE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { resolveProfile, resolveSchemaPath } from "../config.js";
|
|
2
|
+
import { queryData } from "../drizzle-bridge.js";
|
|
3
|
+
import { parseArgs, getString } from "../args.js";
|
|
4
|
+
export const dataCommand = async (args) => {
|
|
5
|
+
const parsed = parseArgs(args);
|
|
6
|
+
const table = parsed.positionals[0];
|
|
7
|
+
if (!table) {
|
|
8
|
+
console.error("error: usage: covara data <table> [--limit n] [--profile name]");
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
try {
|
|
13
|
+
const profile = resolveProfile(cwd, {
|
|
14
|
+
profile: getString(parsed, "profile"),
|
|
15
|
+
url: getString(parsed, "url"),
|
|
16
|
+
});
|
|
17
|
+
const schemaPath = resolveSchemaPath(cwd);
|
|
18
|
+
const limit = getString(parsed, "limit");
|
|
19
|
+
const { rows } = await queryData(cwd, profile, schemaPath, table, {
|
|
20
|
+
limit: limit ? parseInt(limit, 10) : undefined,
|
|
21
|
+
});
|
|
22
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
23
|
+
console.log(`\n(${rows.length} row(s))`);
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.error(`error: ${e instanceof Error ? e.message : String(e)}`);
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../src/cli/commands/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,IAAc,EAAmB,EAAE;IACnE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;QAChF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE;YAClC,OAAO,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC;YACrC,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC;SAC9B,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE;YAChE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;SAC/C,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC;QACzC,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,KAAG,MA2F1C,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { loadConfig, saveConfig, resolveProfile, dialectFromUrl, } from "../config.js";
|
|
2
|
+
import { parseArgs, getString } from "../args.js";
|
|
3
|
+
const DB_HELP = `covara db - manage database connection profiles
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
covara db list
|
|
7
|
+
covara db current
|
|
8
|
+
covara db use <name>
|
|
9
|
+
covara db add <name> --url <url> [--token <token>] [--dialect sqlite|postgres]
|
|
10
|
+
covara db remove <name>
|
|
11
|
+
`;
|
|
12
|
+
export const dbCommand = (args) => {
|
|
13
|
+
const [sub, ...rest] = args;
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
if (!sub || sub === "help" || sub === "--help") {
|
|
16
|
+
console.log(DB_HELP);
|
|
17
|
+
return sub ? 0 : 1;
|
|
18
|
+
}
|
|
19
|
+
if (sub === "list") {
|
|
20
|
+
const config = loadConfig(cwd);
|
|
21
|
+
const names = Object.keys(config.profiles);
|
|
22
|
+
if (names.length === 0) {
|
|
23
|
+
console.log("No profiles configured. Add one with `covara db add <name> --url <url>`.");
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
for (const name of names) {
|
|
27
|
+
const p = config.profiles[name];
|
|
28
|
+
const marker = name === config.active ? "* " : " ";
|
|
29
|
+
console.log(`${marker}${name} [${p.dialect}] ${p.url}`);
|
|
30
|
+
}
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
if (sub === "current") {
|
|
34
|
+
try {
|
|
35
|
+
const p = resolveProfile(cwd);
|
|
36
|
+
console.log(`${p.name} [${p.dialect}] ${p.url}`);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
console.error(`error: ${e instanceof Error ? e.message : String(e)}`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (sub === "use") {
|
|
45
|
+
const name = rest.find((a) => !a.startsWith("-"));
|
|
46
|
+
if (!name) {
|
|
47
|
+
console.error("error: missing profile name (usage: covara db use <name>)");
|
|
48
|
+
return 1;
|
|
49
|
+
}
|
|
50
|
+
const config = loadConfig(cwd);
|
|
51
|
+
if (!config.profiles[name]) {
|
|
52
|
+
console.error(`error: unknown profile "${name}"`);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
config.active = name;
|
|
56
|
+
saveConfig(cwd, config);
|
|
57
|
+
console.log(`Active profile is now "${name}".`);
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
if (sub === "add") {
|
|
61
|
+
const parsed = parseArgs(rest, { aliases: { t: "token", d: "dialect" } });
|
|
62
|
+
const name = parsed.positionals[0];
|
|
63
|
+
const url = getString(parsed, "url");
|
|
64
|
+
if (!name || !url) {
|
|
65
|
+
console.error("error: usage: covara db add <name> --url <url> [--token <token>] [--dialect sqlite|postgres]");
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
const dialect = getString(parsed, "dialect") ?? dialectFromUrl(url);
|
|
69
|
+
const token = getString(parsed, "token");
|
|
70
|
+
const config = loadConfig(cwd);
|
|
71
|
+
config.profiles[name] = { dialect, url, ...(token ? { authToken: token } : {}) };
|
|
72
|
+
if (!config.active)
|
|
73
|
+
config.active = name;
|
|
74
|
+
saveConfig(cwd, config);
|
|
75
|
+
console.log(`Added profile "${name}" [${dialect}].`);
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
if (sub === "remove" || sub === "rm") {
|
|
79
|
+
const name = rest.find((a) => !a.startsWith("-"));
|
|
80
|
+
if (!name) {
|
|
81
|
+
console.error("error: missing profile name (usage: covara db remove <name>)");
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
const config = loadConfig(cwd);
|
|
85
|
+
if (!config.profiles[name]) {
|
|
86
|
+
console.error(`error: unknown profile "${name}"`);
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
delete config.profiles[name];
|
|
90
|
+
if (config.active === name)
|
|
91
|
+
delete config.active;
|
|
92
|
+
saveConfig(cwd, config);
|
|
93
|
+
console.log(`Removed profile "${name}".`);
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
console.error(`error: unknown db subcommand "${sub}"\n`);
|
|
97
|
+
console.log(DB_HELP);
|
|
98
|
+
return 1;
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/cli/commands/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAkG/D,CAAC"}
|