diff --git a/.changeset/migrations-view.md b/.changeset/migrations-view.md new file mode 100644 index 00000000..52ad6c2c --- /dev/null +++ b/.changeset/migrations-view.md @@ -0,0 +1,11 @@ +--- +"@prisma/studio-core": minor +--- + +Add a Prisma Next Migrations view. When the connected database carries a Prisma Next migration ledger (`prisma_contract.ledger`) with at least one applied migration, Studio shows a Migrations navigation item with a newest-first timeline of every applied migration — name, apply time, operation count, destructive-change markers, and compact `+`/`−`/`~` chips summarizing what each migration changed. + +Selecting a migration renders a visual, FigJam-style diff canvas built from the contract snapshots Prisma Next records alongside the ledger: added, removed, and changed models as color-coded cards with per-field before → after details (type, nullability, defaults, primary keys), enum cards, and relation edges. An All models toggle expands to the migration's full schema, switching migrations morphs the canvas over ~500ms instead of rebuilding it, and the selected migration is URL-addressable. + +Collapsible detail panels behind a drag-resizable split show the executed SQL per operation and a Prisma-schema-style line diff of the before/after schema, with long unchanged runs collapsed into click-to-expand folds. + +Databases whose ledger predates contract snapshots keep the timeline and SQL panel and show an update notice in place of the canvas. Requires a database migrated with a Prisma Next version that records contract snapshots for the visual and schema diffs. diff --git a/Architecture/migrations-view.md b/Architecture/migrations-view.md new file mode 100644 index 00000000..fa71d1c0 --- /dev/null +++ b/Architecture/migrations-view.md @@ -0,0 +1,84 @@ +# Prisma Next Migrations View Architecture + +This document is normative for the Studio Migrations view (`view=migrations`). + +The view renders the Prisma Next migration history stored in the connected database. Studio does not read migration bundles from disk and does not talk to the Prisma Next CLI; the database ledger is the single source of truth. + +## Scope + +This architecture governs: + +- detection of the Prisma Next migration ledger and Migrations navigation visibility +- loading and normalizing `prisma_contract.ledger` rows +- the contract snapshot diff engine +- the visual diff canvas and migration timeline list +- demo seeding of a migration history for `pnpm demo:ppg` + +## Canonical Components + +- [`ui/hooks/use-migrations.ts`](../ui/hooks/use-migrations.ts) +- [`ui/studio/views/migrations/contract-diff.ts`](../ui/studio/views/migrations/contract-diff.ts) +- [`ui/studio/views/migrations/diff-layout.ts`](../ui/studio/views/migrations/diff-layout.ts) +- [`ui/studio/views/migrations/MigrationsView.tsx`](../ui/studio/views/migrations/MigrationsView.tsx) +- [`ui/studio/Navigation.tsx`](../ui/studio/Navigation.tsx) +- [`demo/ppg-dev/seed-migrations.ts`](../demo/ppg-dev/seed-migrations.ts) + +## Data Source + +Prisma Next records one row per applied migration in `prisma_contract.ledger`, and each distinct contract IR once in the content-addressed store `prisma_contract.contract` (`core_hash` PK — a contract's storage hash is its identity; see the Migration System subsystem doc in the prisma-next repository). The columns Studio consumes: + +- `ledger.id` — apply order (bigserial) +- `ledger.space` — contract space (`app` for the application schema) +- `ledger.migration_name`, `ledger.migration_hash` — identity; the name is empty for synthesised `db init`/`db update` applies +- `ledger.origin_core_hash`, `ledger.destination_core_hash` — the contract-graph edge; both are contract identifiers that resolve into the store by hash equality +- `ledger.operations` — the executed operation envelopes, including per-step SQL and `operationClass` +- `ledger.created_at` — apply time +- `contract.contract_json` — full contract IR, LEFT JOINed twice (once per edge endpoint); null when no contract is stored under that hash + +Both endpoint snapshots come straight from the joins — a baseline origin (no stored contract) yields a null before-state and diffs against the empty contract; an unresolved origin hash (out-of-band drift, snapshot-less predecessor) yields null rather than a wrong baseline. No client-side chain reconstruction exists. Rows are read through the standard `Adapter.raw` surface, so every executor (direct TCP, BFF, PGlite) works unchanged. Databases bootstrapped before the `contract` table existed are queried without the joins (detection below) — the list still renders, with empty diffs. + +## Detection + +`useMigrationsDetection` derives ledger and contract-table presence purely from introspection data (`introspection.schemas["prisma_contract"].tables["ledger"|"contract"]`); the contract-table flag picks the joined or join-less ledger query. The Migrations navigation item is gated by `useHasMigrationHistory`, which additionally runs a one-row `EXISTS` probe (not a full ledger fetch — snapshots can be megabytes of jsonb): a missing `prisma_contract` schema, a missing ledger table, or an empty ledger all hide the item. Stale `view=migrations` URLs against such a database show the view's empty state rather than breaking navigation. + +## Missing Contract Data + +When the ledger has rows but none of them joins to a contract snapshot (the `contract` table is missing or empty — a database written by a prisma-next predating the 1:1 table), there is nothing to diff: the view keeps the migration list and the SQL panel (both are pure ledger data), hides the All models toggle and Schema button, and replaces the canvas with an upgrade notice pointing at the latest Prisma Next. A single non-null snapshot anywhere renders the normal canvas with whatever data exists. + +## Snapshot Coverage + +Prisma Next writes only each apply's destination contract into the store, yet both endpoints of every edge resolve: every non-baseline origin hash was some predecessor apply's destination hash, so its contract is already stored, and content addressing means a contract revisited by a rollback cycle exists exactly once. The hash join is the correctness guard — there is nothing for Studio to verify or reconstruct client-side. + +## Diff Engine + +`contract-diff.ts` is pure and UI-free: + +1. `parseContractSnapshot` normalizes a contract JSON document into flat models (fields with column, native type, nullability, rendered default, enum linkage, primary-key membership; relations; index/unique signatures) and enums. Malformed documents degrade to an empty snapshot instead of throwing. +2. `diffContracts` classifies every model, field, enum, enum member, relation, and index signature as `added` / `removed` / `changed` / `unchanged`, with per-field change details (type, nullability, default) and aggregate stats. + +Model-level structure comes from the contract's domain plane; storage-plane data (native types, defaults, primary keys, indexes) enriches it through each model's `storage.table` binding. + +## Visual Canvas + +The diff renders on a React Flow canvas (same dependency as the Schema Visualizer) with ELK auto-layout in `diff-layout.ts`. By default only touched models, their direct relation neighbors (rendered dimmed as context), and touched enums become nodes; the `All models` toggle (persisted UI state) expands to every model **and enum** in the migration's contract (unchanged ones in the dimmed context style), and a migration that touches nothing falls back to showing the full schema. Relation edges connect visible nodes, with added relations emphasized and removed relations drawn in the destructive color. + +A model's status is table-anchored: only field or index changes mark it `changed`. Relation-only changes (a back-relation whose foreign key lives in the other table) keep the model `unchanged` — the added or removed relation surfaces through the emphasized edge, never through an amber card. This keeps the amber signal synonymous with "this table's DDL changed". + +The canvas is a single persistent React Flow instance. Node ids are stable (`model:` / `enum:`), so switching migrations swaps node/edge arrays in place: surviving nodes glide to their new ELK positions via a CSS transform transition (see the `migrations-diff-canvas` rules in `ui/index.css`), entering nodes fade in, and the camera animates with `fitView({ duration: 500 })`. MUST NOT key the canvas or its wrapper by migration id — remounting is what causes the jarring full rebuild (and previously wedged exit animations). + +The card styling is deliberately playful (FigJam-inspired): status-colored sticky-note cards with tape accents and deterministic tilt, `+`/`−`/`~` field glyphs, and before → after pills for changed field aspects. See `non-standard-ui.md` for the approved exception. + +Selection state lives in the `migration` URL parameter (nuqs), so a specific migration diff is shareable. + +The per-migration header (title, hash edge, diff-stat chips, view controls) floats over the top edge of the canvas as a translucent backdrop-blurred bar, so the canvas owns the full height of the content pane. + +## Detail Panels + +Two mutually exclusive collapsible panels sit under the canvas in a shared container whose height is user-resizable from a drag handle on its top edge (pointer drag plus ArrowUp/ArrowDown, clamped 120–640px, persisted UI state): + +- **SQL** renders the ledger row's operation envelopes verbatim — labels, operation classes, and executed statements. +- **Schema** renders a Prisma-schema-style diff. `psl-schema.ts` projects each contract snapshot into PSL-shaped text (model/enum blocks, mapped field types, defaults, relations, `@@index`/`@@unique`/`@@map`) and diffs the two texts line-by-line with the `diff` (jsdiff) package, collapsing long unchanged runs. The projection favors diff stability (fixed field ordering, no column alignment padding) over exact `prisma format` output. jsdiff was chosen over `@pierre/diffs` because the latter hard-depends on shiki, which is too heavy for the published bundle; the renderer is isolated in `MigrationSchemaPanel` so it can be swapped. + +## Demo Seeding + +`seed-migrations.ts` replays a fixture captured from the prisma-next `migrations-showcase` example (`demo/ppg-dev/fixtures/prisma-contract-migrations.json`): it recreates the `prisma_contract` schema (marker, ledger, and the hash-keyed contract store), upserts each migration's after-state under its destination hash (`ON CONFLICT DO NOTHING` — the fixture's `contract_json_before` values are intentionally not written; origins resolve as predecessors' destinations), restores the marker and ledger rows, and re-executes every operation's SQL in ledger order so the live schema matches the migration history exactly. Legacy demo volumes are upgraded in place: a `ledger_id`-keyed contract table is re-keyed by destination hash, and a two-column ledger has its after-states moved into the store and the bookend columns dropped. A few showcase rows are inserted so the resulting tables are browsable. diff --git a/Architecture/non-standard-ui.md b/Architecture/non-standard-ui.md index 62397996..91c58d9a 100644 --- a/Architecture/non-standard-ui.md +++ b/Architecture/non-standard-ui.md @@ -186,6 +186,19 @@ It deliberately excludes: These are the current high-signal places where Studio is bypassing a plausible standard ShadCN component or composition pattern. +### Migration Diff Canvas Cards + +- Canonical components: + - [`ui/studio/views/migrations/MigrationsView.tsx`](ui/studio/views/migrations/MigrationsView.tsx) + - [`ui/studio/views/migrations/diff-layout.ts`](ui/studio/views/migrations/diff-layout.ts) +- Closest standard ShadCN alternative: + - `Card` with `Badge` +- Why it stays non-standard: + - The Migrations view renders model/enum diff cards as React Flow custom nodes on a pan/zoom canvas with ELK layout; ShadCN `Card` cannot express canvas nodes with connection handles, status-driven color systems, or per-field diff glyph rows. + - The FigJam-inspired treatment (status-colored sticky-note cards, tape accents, deterministic tilt, before → after change pills) is a deliberate product decision for this view so schema changes read as an approachable visual story rather than a table. +- Required internals: + - `Badge`, `Button`, `Skeleton` for the surrounding chrome; the timeline list items are custom buttons because they combine an index chip, name, timestamp, and diff-stat chips in one selectable row, which `Button` alone does not model. + ### Introspection Status Notice - Files: diff --git a/FEATURES.md b/FEATURES.md index d18c0018..b617da84 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -155,6 +155,16 @@ The table and recommendation text label returned-row volume as `Rows Returned`; When Studio's shared `llm` hook is available, the query table adds an Analysis column that analyzes newly observed query groups in the background, one at a time, and stops automatic work after the first five groups. Rows show a running indicator, a manual Analyze action, and a completed all-good, info, or warning icon; the detail sheet uses the same analysis queue for manual recommendations. Without that hook, the AI analysis UI is hidden. If an embedder does not provide query insights, Studio hides the `Queries` menu item and stale `view=queries` URLs fall back to the normal default view. +## Prisma Next Migrations View + +When the connected database carries a Prisma Next migration ledger (`prisma_contract.ledger`) with at least one applied migration, Studio shows a `Migrations` item in the main navigation; databases without the `prisma_contract` schema, without the ledger table, or with an empty ledger never see the entry. +The view lists every applied migration newest-first — name, apply time, operation count, a destructive-change marker, and compact `+`/`−`/`~` chips summarizing what each migration did to models, fields, enums, and indexes. +Selecting a migration renders a visual, UML-style diff on a pan/zoom canvas built from the contract snapshots Prisma Next records alongside the ledger (a content-addressed store joined onto each migration's origin/destination hashes): added models appear as green cards, removed models red with strikethrough, changed models amber with per-field detail rows (type, nullability, and default transitions rendered as before → after), plus enum cards and relation edges; untouched neighbor models render dimmed for context, and an `All models` toggle expands the canvas to the migration's full schema, including unchanged enums. +A model only turns amber when its own table changed (fields or indexes); gaining a back-relation whose foreign key lives in the other table keeps the model dimmed while the new relation edge is emphasized instead. +Switching between migrations morphs the canvas rather than rebuilding it: surviving model cards glide to their new layout positions and the camera refits over ~500ms, so stepping through adjacent migrations reads as one continuous story. +Collapsible detail panels show the executed SQL (per-operation class and exact statements) and a Prisma-schema-style diff of the migration — a unified, color-coded line diff of the before/after schema with long unchanged runs collapsed into click-to-expand folds — and the split between canvas and panel is resizable from a drag handle. The migration header floats over the canvas top edge so the diagram gets the full content height. The selected migration is tracked in the URL so views can be shared and revisited. +When the ledger has migrations but no contract snapshots to diff (a database written by an older Prisma Next), the list and SQL panel keep working and the canvas is replaced by a notice asking to update Prisma Next. + ## Data Grid Browsing Table data is shown in a grid with server-backed pagination, filtered-row counts, loading feedback, and explicit empty states. diff --git a/demo/ppg-dev/fixtures/prisma-contract-migrations.json b/demo/ppg-dev/fixtures/prisma-contract-migrations.json new file mode 100644 index 00000000..d76d864e --- /dev/null +++ b/demo/ppg-dev/fixtures/prisma-contract-migrations.json @@ -0,0 +1,48386 @@ +{ + "generatedAt": "2026-07-02T22:37:56.072Z", + "marker": [ + { + "space": "app", + "core_hash": "sha256:811cea82e78e9812ffc3f4fc824f08655fa6a58e10118fc9d7a71e5bd2da0e57", + "profile_hash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "contract_json": null, + "canonical_version": null, + "app_tag": null, + "meta": {}, + "invariants": [], + "updated_at": "2026-07-02T22:37:54.866Z" + } + ], + "ledger": [ + { + "id": "1", + "space": "app", + "migration_name": "20260702T2236_init_users", + "migration_hash": "sha256:ba055565be02c8f44716b1e61c3c50c973a482d40ad1f57e161b720f74ddbcb8", + "origin_core_hash": "sha256:empty", + "destination_core_hash": "sha256:09d8d8221c4ee0733254e175363eb25d28c44f1d3ce5e56128ca859ec7065cb4", + "contract_json_before": null, + "contract_json_after": { + "meta": {}, + "roots": { + "user": { + "model": "User", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": {} + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + } + } + } + } + }, + "storageHash": "sha256:09d8d8221c4ee0733254e175363eb25d28c44f1d3ce5e56128ca859ec7065cb4" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:fe46779ef51485a49fbbedb286ca1ec733f51ea9c47f30b76262765459fe3722" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "schema.public", + "label": "Create schema \"public\"", + "target": { + "id": "postgres" + }, + "execute": [ + { + "sql": "CREATE SCHEMA IF NOT EXISTS \"public\"", + "params": [], + "description": "Create schema \"public\"" + } + ], + "precheck": [], + "postcheck": [], + "operationClass": "additive" + }, + { + "id": "table.user", + "label": "Create table \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "user", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"user\" (\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"email\" text NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"name\" text NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"user\"" + } + ], + "summary": "Creates table \"user\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"user\"" + ], + "description": "ensure table \"user\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"user\"" + ], + "description": "verify table \"user\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:36:42.953Z" + }, + { + "id": "2", + "space": "app", + "migration_name": "20260702T2236_add_projects", + "migration_hash": "sha256:74de56c6c5d77f1ac04b7736360507cae95500a4f0fe9edac1ff0a9fe9da133d", + "origin_core_hash": "sha256:09d8d8221c4ee0733254e175363eb25d28c44f1d3ce5e56128ca859ec7065cb4", + "destination_core_hash": "sha256:bb8d232f1a452a27d9254f21951cecf7e2bfa0d51324609b1fbe2c2f26d05538", + "contract_json_before": { + "meta": {}, + "roots": { + "user": { + "model": "User", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": {} + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + } + } + } + } + }, + "storageHash": "sha256:09d8d8221c4ee0733254e175363eb25d28c44f1d3ce5e56128ca859ec7065cb4" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:fe46779ef51485a49fbbedb286ca1ec733f51ea9c47f30b76262765459fe3722" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:bb8d232f1a452a27d9254f21951cecf7e2bfa0d51324609b1fbe2c2f26d05538" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:530c00a378586f18244d826d2c9a83965f47b66851ab1d5eff26c9bf222d2fd5" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.project", + "label": "Create table \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "project", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"project\" (\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"description\" text,\n \"id\" \"uuid\" NOT NULL,\n \"name\" text NOT NULL,\n \"ownerId\" \"uuid\" NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"project\"" + } + ], + "summary": "Creates table \"project\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"project\"" + ], + "description": "ensure table \"project\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"project\"" + ], + "description": "verify table \"project\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.project.project_ownerId_idx", + "label": "Create index \"project_ownerId_idx\" on \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "project_ownerId_idx", + "table": "project", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"project_ownerId_idx\" ON \"public\".\"project\" (\"ownerId\")", + "description": "create index \"project_ownerId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"project_ownerId_idx\"" + ], + "description": "ensure index \"project_ownerId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"project_ownerId_idx\"" + ], + "description": "verify index \"project_ownerId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.project.project_ownerId_fkey", + "label": "Add foreign key \"project_ownerId_fkey\" on \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "project_ownerId_fkey", + "table": "project", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"project\"\nADD CONSTRAINT \"project_ownerId_fkey\"\nFOREIGN KEY (\"ownerId\")\nREFERENCES \"public\".\"user\" (\"id\")", + "description": "add FK \"project_ownerId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "project_ownerId_fkey", + "public", + "\"public\".\"project\"" + ], + "description": "ensure FK \"project_ownerId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "project_ownerId_fkey", + "public", + "\"public\".\"project\"" + ], + "description": "verify FK \"project_ownerId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:36:46.612Z" + }, + { + "id": "3", + "space": "app", + "migration_name": "20260702T2236_add_tasks", + "migration_hash": "sha256:15145565c5d2f233ff9945b3408d8d415c421de62dd87cea1afe94cc039d38ea", + "origin_core_hash": "sha256:bb8d232f1a452a27d9254f21951cecf7e2bfa0d51324609b1fbe2c2f26d05538", + "destination_core_hash": "sha256:287b8aaf3f4710c3e004badc86969ed588983f11860642c60d2c112bd9c5a6c0", + "contract_json_before": { + "meta": {}, + "roots": { + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:bb8d232f1a452a27d9254f21951cecf7e2bfa0d51324609b1fbe2c2f26d05538" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:530c00a378586f18244d826d2c9a83965f47b66851ab1d5eff26c9bf222d2fd5" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:287b8aaf3f4710c3e004badc86969ed588983f11860642c60d2c112bd9c5a6c0" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.task", + "label": "Create table \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"task\" (\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"done\" bool DEFAULT false NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"projectId\" \"uuid\" NOT NULL,\n \"title\" text NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"task\"" + } + ], + "summary": "Creates table \"task\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task\"" + ], + "description": "ensure table \"task\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task\"" + ], + "description": "verify table \"task\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.task.task_projectId_idx", + "label": "Create index \"task_projectId_idx\" on \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task_projectId_idx", + "table": "task", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"task_projectId_idx\" ON \"public\".\"task\" (\"projectId\")", + "description": "create index \"task_projectId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_projectId_idx\"" + ], + "description": "ensure index \"task_projectId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_projectId_idx\"" + ], + "description": "verify index \"task_projectId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.task.task_projectId_fkey", + "label": "Add foreign key \"task_projectId_fkey\" on \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task_projectId_fkey", + "table": "task", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\"\nADD CONSTRAINT \"task_projectId_fkey\"\nFOREIGN KEY (\"projectId\")\nREFERENCES \"public\".\"project\" (\"id\")", + "description": "add FK \"task_projectId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_projectId_fkey", + "public", + "\"public\".\"task\"" + ], + "description": "ensure FK \"task_projectId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_projectId_fkey", + "public", + "\"public\".\"task\"" + ], + "description": "verify FK \"task_projectId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:36:50.313Z" + }, + { + "id": "4", + "space": "app", + "migration_name": "20260702T2236_user_profiles", + "migration_hash": "sha256:c958ae70b466082ceabe6f7bc46c9c253099baf59a471685ff5e9d6af88c3683", + "origin_core_hash": "sha256:287b8aaf3f4710c3e004badc86969ed588983f11860642c60d2c112bd9c5a6c0", + "destination_core_hash": "sha256:5fe2fe95c3baa9f680109f850cb3464a43d3fa6dedb2b1943c6e378d4fb3a672", + "contract_json_before": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:287b8aaf3f4710c3e004badc86969ed588983f11860642c60d2c112bd9c5a6c0" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:5fe2fe95c3baa9f680109f850cb3464a43d3fa6dedb2b1943c6e378d4fb3a672" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.user.avatarUrl", + "label": "Add column \"avatarUrl\" to \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "avatarUrl", + "table": "user", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\" ADD COLUMN \"avatarUrl\" text", + "description": "add column \"avatarUrl\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "avatarUrl" + ], + "description": "ensure column \"avatarUrl\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "avatarUrl" + ], + "description": "verify column \"avatarUrl\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "column.public.user.bio", + "label": "Add column \"bio\" to \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "bio", + "table": "user", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\" ADD COLUMN \"bio\" text", + "description": "add column \"bio\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "bio" + ], + "description": "ensure column \"bio\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "bio" + ], + "description": "verify column \"bio\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:36:54.005Z" + }, + { + "id": "5", + "space": "app", + "migration_name": "20260702T2236_task_priorities", + "migration_hash": "sha256:421e54eaa9032b292edec977b46724b2a44909912dc7cca61921b50985afb515", + "origin_core_hash": "sha256:5fe2fe95c3baa9f680109f850cb3464a43d3fa6dedb2b1943c6e378d4fb3a672", + "destination_core_hash": "sha256:bca0859a335d401e4909a39567c5d329d495c59f574062fe9218fd513f4334de", + "contract_json_before": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + } + } + } + }, + "storageHash": "sha256:5fe2fe95c3baa9f680109f850cb3464a43d3fa6dedb2b1943c6e378d4fb3a672" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:bca0859a335d401e4909a39567c5d329d495c59f574062fe9218fd513f4334de" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.task.priority", + "label": "Add column \"priority\" to \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "priority", + "table": "task", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD COLUMN \"priority\" text DEFAULT 'low' NOT NULL", + "description": "add column \"priority\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "priority" + ], + "description": "ensure column \"priority\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "priority" + ], + "description": "verify column \"priority\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "checkConstraint.task.task_priority_check", + "label": "Add check constraint \"task_priority_check\" on \"task\".\"priority\"", + "target": { + "id": "postgres", + "details": { + "name": "task_priority_check", + "table": "task", + "schema": "public", + "objectType": "checkConstraint" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD CONSTRAINT \"task_priority_check\" CHECK (\"priority\" IN ('low', 'medium', 'high'))", + "description": "add check constraint \"task_priority_check\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_priority_check", + "public", + "\"public\".\"task\"" + ], + "description": "ensure constraint \"task_priority_check\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_priority_check", + "public", + "\"public\".\"task\"" + ], + "description": "verify constraint \"task_priority_check\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:36:57.664Z" + }, + { + "id": "6", + "space": "app", + "migration_name": "20260702T2237_add_comments", + "migration_hash": "sha256:0d35249e72eb5a67fdd7a65fe0efaa3dd7b32a96ac58c11f2f635d8996890301", + "origin_core_hash": "sha256:bca0859a335d401e4909a39567c5d329d495c59f574062fe9218fd513f4334de", + "destination_core_hash": "sha256:d82ebb1dcfd7b63b725803e71400e7c4a2c2e8b8f91ec421722627f3e9e2cf2d", + "contract_json_before": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:bca0859a335d401e4909a39567c5d329d495c59f574062fe9218fd513f4334de" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:6e64a0707487f5cd31222c0ffdfcf5b3908a8b54a00592b33f8aaa9553784151" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:d82ebb1dcfd7b63b725803e71400e7c4a2c2e8b8f91ec421722627f3e9e2cf2d" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:2270c6634e2720f4a6c9ea9997ed7af3198a3af8e947c4a2238e8c762dfff5ed" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.comment", + "label": "Create table \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"comment\" (\n \"authorId\" \"uuid\" NOT NULL,\n \"body\" text NOT NULL,\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"taskId\" \"uuid\" NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"comment\"" + } + ], + "summary": "Creates table \"comment\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"comment\"" + ], + "description": "ensure table \"comment\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"comment\"" + ], + "description": "verify table \"comment\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.comment.comment_taskId_idx", + "label": "Create index \"comment_taskId_idx\" on \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment_taskId_idx", + "table": "comment", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"comment_taskId_idx\" ON \"public\".\"comment\" (\"taskId\")", + "description": "create index \"comment_taskId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"comment_taskId_idx\"" + ], + "description": "ensure index \"comment_taskId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"comment_taskId_idx\"" + ], + "description": "verify index \"comment_taskId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.comment.comment_authorId_idx", + "label": "Create index \"comment_authorId_idx\" on \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment_authorId_idx", + "table": "comment", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"comment_authorId_idx\" ON \"public\".\"comment\" (\"authorId\")", + "description": "create index \"comment_authorId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"comment_authorId_idx\"" + ], + "description": "ensure index \"comment_authorId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"comment_authorId_idx\"" + ], + "description": "verify index \"comment_authorId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.comment.comment_taskId_fkey", + "label": "Add foreign key \"comment_taskId_fkey\" on \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment_taskId_fkey", + "table": "comment", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"comment\"\nADD CONSTRAINT \"comment_taskId_fkey\"\nFOREIGN KEY (\"taskId\")\nREFERENCES \"public\".\"task\" (\"id\")", + "description": "add FK \"comment_taskId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "comment_taskId_fkey", + "public", + "\"public\".\"comment\"" + ], + "description": "ensure FK \"comment_taskId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "comment_taskId_fkey", + "public", + "\"public\".\"comment\"" + ], + "description": "verify FK \"comment_taskId_fkey\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.comment.comment_authorId_fkey", + "label": "Add foreign key \"comment_authorId_fkey\" on \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment_authorId_fkey", + "table": "comment", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"comment\"\nADD CONSTRAINT \"comment_authorId_fkey\"\nFOREIGN KEY (\"authorId\")\nREFERENCES \"public\".\"user\" (\"id\")", + "description": "add FK \"comment_authorId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "comment_authorId_fkey", + "public", + "\"public\".\"comment\"" + ], + "description": "ensure FK \"comment_authorId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "comment_authorId_fkey", + "public", + "\"public\".\"comment\"" + ], + "description": "verify FK \"comment_authorId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:01.454Z" + }, + { + "id": "7", + "space": "app", + "migration_name": "20260702T2237_add_tags", + "migration_hash": "sha256:291e13a5e8abb424208eaeafce76d8488d82ac9f72fa8a598add0ecccf71e622", + "origin_core_hash": "sha256:d82ebb1dcfd7b63b725803e71400e7c4a2c2e8b8f91ec421722627f3e9e2cf2d", + "destination_core_hash": "sha256:2a12786da5e4607f51eeffe1942d9298fadb53545f8bf43934b2e9000e084e76", + "contract_json_before": { + "meta": {}, + "roots": { + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:d82ebb1dcfd7b63b725803e71400e7c4a2c2e8b8f91ec421722627f3e9e2cf2d" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:2270c6634e2720f4a6c9ea9997ed7af3198a3af8e947c4a2238e8c762dfff5ed" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:2a12786da5e4607f51eeffe1942d9298fadb53545f8bf43934b2e9000e084e76" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.tag", + "label": "Create table \"tag\"", + "target": { + "id": "postgres", + "details": { + "name": "tag", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"tag\" (\n \"id\" \"uuid\" NOT NULL,\n \"label\" text NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"tag\"" + } + ], + "summary": "Creates table \"tag\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"tag\"" + ], + "description": "ensure table \"tag\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"tag\"" + ], + "description": "verify table \"tag\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "table.task_tag", + "label": "Create table \"task_tag\"", + "target": { + "id": "postgres", + "details": { + "name": "task_tag", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"task_tag\" (\n \"tagId\" \"uuid\" NOT NULL,\n \"taskId\" \"uuid\" NOT NULL,\n PRIMARY KEY (\"taskId\", \"tagId\")\n)", + "params": [], + "description": "create table \"task_tag\"" + } + ], + "summary": "Creates table \"task_tag\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag\"" + ], + "description": "ensure table \"task_tag\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag\"" + ], + "description": "verify table \"task_tag\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "unique.tag.tag_label_key", + "label": "Add unique constraint on \"tag\" (label)", + "target": { + "id": "postgres", + "details": { + "name": "tag_label_key", + "table": "tag", + "schema": "public", + "objectType": "unique" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"tag\" ADD CONSTRAINT \"tag_label_key\" UNIQUE (\"label\")", + "description": "add unique constraint \"tag_label_key\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "tag_label_key", + "public", + "\"public\".\"tag\"" + ], + "description": "ensure constraint \"tag_label_key\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "tag_label_key", + "public", + "\"public\".\"tag\"" + ], + "description": "verify constraint \"tag_label_key\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.task_tag.task_tag_taskId_idx", + "label": "Create index \"task_tag_taskId_idx\" on \"task_tag\"", + "target": { + "id": "postgres", + "details": { + "name": "task_tag_taskId_idx", + "table": "task_tag", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"task_tag_taskId_idx\" ON \"public\".\"task_tag\" (\"taskId\")", + "description": "create index \"task_tag_taskId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag_taskId_idx\"" + ], + "description": "ensure index \"task_tag_taskId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag_taskId_idx\"" + ], + "description": "verify index \"task_tag_taskId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.task_tag.task_tag_tagId_idx", + "label": "Create index \"task_tag_tagId_idx\" on \"task_tag\"", + "target": { + "id": "postgres", + "details": { + "name": "task_tag_tagId_idx", + "table": "task_tag", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"task_tag_tagId_idx\" ON \"public\".\"task_tag\" (\"tagId\")", + "description": "create index \"task_tag_tagId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag_tagId_idx\"" + ], + "description": "ensure index \"task_tag_tagId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_tag_tagId_idx\"" + ], + "description": "verify index \"task_tag_tagId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.task_tag.task_tag_taskId_fkey", + "label": "Add foreign key \"task_tag_taskId_fkey\" on \"task_tag\"", + "target": { + "id": "postgres", + "details": { + "name": "task_tag_taskId_fkey", + "table": "task_tag", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task_tag\"\nADD CONSTRAINT \"task_tag_taskId_fkey\"\nFOREIGN KEY (\"taskId\")\nREFERENCES \"public\".\"task\" (\"id\")", + "description": "add FK \"task_tag_taskId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_tag_taskId_fkey", + "public", + "\"public\".\"task_tag\"" + ], + "description": "ensure FK \"task_tag_taskId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_tag_taskId_fkey", + "public", + "\"public\".\"task_tag\"" + ], + "description": "verify FK \"task_tag_taskId_fkey\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.task_tag.task_tag_tagId_fkey", + "label": "Add foreign key \"task_tag_tagId_fkey\" on \"task_tag\"", + "target": { + "id": "postgres", + "details": { + "name": "task_tag_tagId_fkey", + "table": "task_tag", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task_tag\"\nADD CONSTRAINT \"task_tag_tagId_fkey\"\nFOREIGN KEY (\"tagId\")\nREFERENCES \"public\".\"tag\" (\"id\")", + "description": "add FK \"task_tag_tagId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_tag_tagId_fkey", + "public", + "\"public\".\"task_tag\"" + ], + "description": "ensure FK \"task_tag_tagId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_tag_tagId_fkey", + "public", + "\"public\".\"task_tag\"" + ], + "description": "verify FK \"task_tag_tagId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:05.268Z" + }, + { + "id": "8", + "space": "app", + "migration_name": "20260702T2237_task_due_dates", + "migration_hash": "sha256:610633f1907e79052a1804f180f1060ea6f743ee12a08c005886d5c7748ca426", + "origin_core_hash": "sha256:2a12786da5e4607f51eeffe1942d9298fadb53545f8bf43934b2e9000e084e76", + "destination_core_hash": "sha256:6ed4f42f90e412f2e8fabe6818e8f65fdbdb1f1f40612b16de8aaa6493fc4b49", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:2a12786da5e4607f51eeffe1942d9298fadb53545f8bf43934b2e9000e084e76" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:6ed4f42f90e412f2e8fabe6818e8f65fdbdb1f1f40612b16de8aaa6493fc4b49" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.task.dueAt", + "label": "Add column \"dueAt\" to \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "dueAt", + "table": "task", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD COLUMN \"dueAt\" timestamptz", + "description": "add column \"dueAt\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "dueAt" + ], + "description": "ensure column \"dueAt\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "dueAt" + ], + "description": "verify column \"dueAt\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.task.task_projectId_dueAt_idx", + "label": "Create index \"task_projectId_dueAt_idx\" on \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task_projectId_dueAt_idx", + "table": "task", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"task_projectId_dueAt_idx\" ON \"public\".\"task\" (\"projectId\", \"dueAt\")", + "description": "create index \"task_projectId_dueAt_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_projectId_dueAt_idx\"" + ], + "description": "ensure index \"task_projectId_dueAt_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_projectId_dueAt_idx\"" + ], + "description": "verify index \"task_projectId_dueAt_idx\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:09.040Z" + }, + { + "id": "9", + "space": "app", + "migration_name": "20260702T2237_unique_user_email", + "migration_hash": "sha256:2ac5ff3fc5c61b050a04c829add9d293314728a98868e995a42263ce3c6e91df", + "origin_core_hash": "sha256:6ed4f42f90e412f2e8fabe6818e8f65fdbdb1f1f40612b16de8aaa6493fc4b49", + "destination_core_hash": "sha256:d976fba98257e7fc59bfad66e29093b3ea87474b1d5e891c8616662de28bbe38", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:6ed4f42f90e412f2e8fabe6818e8f65fdbdb1f1f40612b16de8aaa6493fc4b49" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:d976fba98257e7fc59bfad66e29093b3ea87474b1d5e891c8616662de28bbe38" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "unique.user.user_email_key", + "label": "Add unique constraint on \"user\" (email)", + "target": { + "id": "postgres", + "details": { + "name": "user_email_key", + "table": "user", + "schema": "public", + "objectType": "unique" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\" ADD CONSTRAINT \"user_email_key\" UNIQUE (\"email\")", + "description": "add unique constraint \"user_email_key\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "user_email_key", + "public", + "\"public\".\"user\"" + ], + "description": "ensure constraint \"user_email_key\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "user_email_key", + "public", + "\"public\".\"user\"" + ], + "description": "verify constraint \"user_email_key\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:12.701Z" + }, + { + "id": "10", + "space": "app", + "migration_name": "20260702T2237_add_teams", + "migration_hash": "sha256:bded9c039db56df89f2a69f4c07ddaed97fd91d900c6013657e684780674aeb5", + "origin_core_hash": "sha256:d976fba98257e7fc59bfad66e29093b3ea87474b1d5e891c8616662de28bbe38", + "destination_core_hash": "sha256:c87b2bb8759d7d130485be54aced7529030b57b3bb609f7eeb5c0c56f7f30188", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:d976fba98257e7fc59bfad66e29093b3ea87474b1d5e891c8616662de28bbe38" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:371e33dd4f6d1bad6a47e47649ff273251a8d37e9d919789b56d78fe241a3b50" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:c87b2bb8759d7d130485be54aced7529030b57b3bb609f7eeb5c0c56f7f30188" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.team", + "label": "Create table \"team\"", + "target": { + "id": "postgres", + "details": { + "name": "team", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"team\" (\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"name\" text NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"team\"" + } + ], + "summary": "Creates table \"team\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"team\"" + ], + "description": "ensure table \"team\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"team\"" + ], + "description": "verify table \"team\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "column.public.user.teamId", + "label": "Add column \"teamId\" to \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "teamId", + "table": "user", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\" ADD COLUMN \"teamId\" \"uuid\"", + "description": "add column \"teamId\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "teamId" + ], + "description": "ensure column \"teamId\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "teamId" + ], + "description": "verify column \"teamId\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.user.user_teamId_idx", + "label": "Create index \"user_teamId_idx\" on \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "user_teamId_idx", + "table": "user", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"user_teamId_idx\" ON \"public\".\"user\" (\"teamId\")", + "description": "create index \"user_teamId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"user_teamId_idx\"" + ], + "description": "ensure index \"user_teamId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"user_teamId_idx\"" + ], + "description": "verify index \"user_teamId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.user.user_teamId_fkey", + "label": "Add foreign key \"user_teamId_fkey\" on \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "user_teamId_fkey", + "table": "user", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\"\nADD CONSTRAINT \"user_teamId_fkey\"\nFOREIGN KEY (\"teamId\")\nREFERENCES \"public\".\"team\" (\"id\")", + "description": "add FK \"user_teamId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "user_teamId_fkey", + "public", + "\"public\".\"user\"" + ], + "description": "ensure FK \"user_teamId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "user_teamId_fkey", + "public", + "\"public\".\"user\"" + ], + "description": "verify FK \"user_teamId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:16.518Z" + }, + { + "id": "11", + "space": "app", + "migration_name": "20260702T2237_project_soft_delete", + "migration_hash": "sha256:44e83aba64db4648f8236d0c69a953daba513c58e65125250d19a3563f3a28f6", + "origin_core_hash": "sha256:c87b2bb8759d7d130485be54aced7529030b57b3bb609f7eeb5c0c56f7f30188", + "destination_core_hash": "sha256:147ca21ac862fc390d30e4ca179bc41a64bee08094f47a57aea7f6aee4320e75", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:c87b2bb8759d7d130485be54aced7529030b57b3bb609f7eeb5c0c56f7f30188" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:147ca21ac862fc390d30e4ca179bc41a64bee08094f47a57aea7f6aee4320e75" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.project.deletedAt", + "label": "Add column \"deletedAt\" to \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "deletedAt", + "table": "project", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"project\" ADD COLUMN \"deletedAt\" timestamptz", + "description": "add column \"deletedAt\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "project", + "deletedAt" + ], + "description": "ensure column \"deletedAt\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "project", + "deletedAt" + ], + "description": "verify column \"deletedAt\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.project.project_deletedAt_idx", + "label": "Create index \"project_deletedAt_idx\" on \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "project_deletedAt_idx", + "table": "project", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"project_deletedAt_idx\" ON \"public\".\"project\" (\"deletedAt\")", + "description": "create index \"project_deletedAt_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"project_deletedAt_idx\"" + ], + "description": "ensure index \"project_deletedAt_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"project_deletedAt_idx\"" + ], + "description": "verify index \"project_deletedAt_idx\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:20.288Z" + }, + { + "id": "12", + "space": "app", + "migration_name": "20260702T2237_task_status", + "migration_hash": "sha256:7c80c0c5955a8bc6160ecb6448184778e7ecc588fa3f72949bd81f2d7418464d", + "origin_core_hash": "sha256:147ca21ac862fc390d30e4ca179bc41a64bee08094f47a57aea7f6aee4320e75", + "destination_core_hash": "sha256:e5855850dc9f7adae3cfb49d236bc805e983b97f07e9dc763b569a5ace15a92a", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + } + } + } + } + }, + "storageHash": "sha256:147ca21ac862fc390d30e4ca179bc41a64bee08094f47a57aea7f6aee4320e75" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:e5855850dc9f7adae3cfb49d236bc805e983b97f07e9dc763b569a5ace15a92a" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.task.status", + "label": "Add column \"status\" to \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "status", + "table": "task", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD COLUMN \"status\" text DEFAULT 'todo' NOT NULL", + "description": "add column \"status\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "status" + ], + "description": "ensure column \"status\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "status" + ], + "description": "verify column \"status\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "checkConstraint.task.task_status_check", + "label": "Add check constraint \"task_status_check\" on \"task\".\"status\"", + "target": { + "id": "postgres", + "details": { + "name": "task_status_check", + "table": "task", + "schema": "public", + "objectType": "checkConstraint" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD CONSTRAINT \"task_status_check\" CHECK (\"status\" IN ('todo', 'in_progress', 'done'))", + "description": "add check constraint \"task_status_check\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_status_check", + "public", + "\"public\".\"task\"" + ], + "description": "ensure constraint \"task_status_check\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_status_check", + "public", + "\"public\".\"task\"" + ], + "description": "verify constraint \"task_status_check\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:24.015Z" + }, + { + "id": "13", + "space": "app", + "migration_name": "20260702T2237_drop_task_done_flag", + "migration_hash": "sha256:4903f60742ab9b937978e95938c8b5698fc0b83269c46c4a7370dffdd45471b5", + "origin_core_hash": "sha256:e5855850dc9f7adae3cfb49d236bc805e983b97f07e9dc763b569a5ace15a92a", + "destination_core_hash": "sha256:591a0d59d912bfab24d5568fa205c7db548d417e27e65f42e50e3e894778c039", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "done": { + "type": { + "kind": "scalar", + "codecId": "pg/bool@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "done": { + "column": "done" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "done": { + "codecId": "pg/bool@1", + "default": { + "kind": "literal", + "value": false + }, + "nullable": false, + "nativeType": "bool" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:e5855850dc9f7adae3cfb49d236bc805e983b97f07e9dc763b569a5ace15a92a" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:591a0d59d912bfab24d5568fa205c7db548d417e27e65f42e50e3e894778c039" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "dropColumn.task.done", + "label": "Drop column \"done\" from \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "done", + "table": "task", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" DROP COLUMN \"done\"", + "description": "drop column \"done\"" + } + ], + "precheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "done" + ], + "description": "ensure column \"done\" exists" + } + ], + "postcheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "done" + ], + "description": "verify column \"done\" does not exist" + } + ], + "operationClass": "destructive" + } + ], + "created_at": "2026-07-02T22:37:27.740Z" + }, + { + "id": "14", + "space": "app", + "migration_name": "20260702T2237_add_activity_log", + "migration_hash": "sha256:d52e8b4b4d4a44e91b414ab63f3e249259dc255fc41dbbdddd64c20aad505cbf", + "origin_core_hash": "sha256:591a0d59d912bfab24d5568fa205c7db548d417e27e65f42e50e3e894778c039", + "destination_core_hash": "sha256:d926ffc1c262369eed92127bce049487b9905e4692936330f11993b88ca3d744", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:591a0d59d912bfab24d5568fa205c7db548d417e27e65f42e50e3e894778c039" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:baf85b2c88194ac4bbf308faf0efc4f3a8a857cd46d142f82bcdb9fa17b686d8" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:d926ffc1c262369eed92127bce049487b9905e4692936330f11993b88ca3d744" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:4c8d3d3e993fcb230845dec79fba4df140eece06358a82d760c74158b074dc46" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.activity_log", + "label": "Create table \"activity_log\"", + "target": { + "id": "postgres", + "details": { + "name": "activity_log", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"activity_log\" (\n \"actorId\" \"uuid\" NOT NULL,\n \"createdAt\" timestamptz DEFAULT (now()) NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"kind\" text NOT NULL,\n \"payload\" jsonb,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"activity_log\"" + } + ], + "summary": "Creates table \"activity_log\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log\"" + ], + "description": "ensure table \"activity_log\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log\"" + ], + "description": "verify table \"activity_log\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.activity_log.activity_log_actorId_idx", + "label": "Create index \"activity_log_actorId_idx\" on \"activity_log\"", + "target": { + "id": "postgres", + "details": { + "name": "activity_log_actorId_idx", + "table": "activity_log", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"activity_log_actorId_idx\" ON \"public\".\"activity_log\" (\"actorId\")", + "description": "create index \"activity_log_actorId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log_actorId_idx\"" + ], + "description": "ensure index \"activity_log_actorId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log_actorId_idx\"" + ], + "description": "verify index \"activity_log_actorId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.activity_log.activity_log_actorId_fkey", + "label": "Add foreign key \"activity_log_actorId_fkey\" on \"activity_log\"", + "target": { + "id": "postgres", + "details": { + "name": "activity_log_actorId_fkey", + "table": "activity_log", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"activity_log\"\nADD CONSTRAINT \"activity_log_actorId_fkey\"\nFOREIGN KEY (\"actorId\")\nREFERENCES \"public\".\"user\" (\"id\")", + "description": "add FK \"activity_log_actorId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "activity_log_actorId_fkey", + "public", + "\"public\".\"activity_log\"" + ], + "description": "ensure FK \"activity_log_actorId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "activity_log_actorId_fkey", + "public", + "\"public\".\"activity_log\"" + ], + "description": "verify FK \"activity_log_actorId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:31.556Z" + }, + { + "id": "15", + "space": "app", + "migration_name": "20260702T2237_add_attachments", + "migration_hash": "sha256:7899d248e22fb849ac75b460ca455ff606474226aa639448e98ee52df3ecc97a", + "origin_core_hash": "sha256:d926ffc1c262369eed92127bce049487b9905e4692936330f11993b88ca3d744", + "destination_core_hash": "sha256:3527520ac103e0abecf2b605944f6435a659ee4c54e08909ab86e7fb1d42f8bf", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:d926ffc1c262369eed92127bce049487b9905e4692936330f11993b88ca3d744" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:4c8d3d3e993fcb230845dec79fba4df140eece06358a82d760c74158b074dc46" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:3527520ac103e0abecf2b605944f6435a659ee4c54e08909ab86e7fb1d42f8bf" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:59dd46584b014783f6f36a0155ba2f0015555a2e6d46de7201d1a120be5f3cb6" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.attachment", + "label": "Create table \"attachment\"", + "target": { + "id": "postgres", + "details": { + "name": "attachment", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"attachment\" (\n \"fileName\" text NOT NULL,\n \"id\" \"uuid\" NOT NULL,\n \"mimeType\" text NOT NULL,\n \"sizeBytes\" int8 NOT NULL,\n \"taskId\" \"uuid\" NOT NULL,\n \"uploadedAt\" timestamptz DEFAULT (now()) NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"attachment\"" + } + ], + "summary": "Creates table \"attachment\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"attachment\"" + ], + "description": "ensure table \"attachment\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"attachment\"" + ], + "description": "verify table \"attachment\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.attachment.attachment_taskId_idx", + "label": "Create index \"attachment_taskId_idx\" on \"attachment\"", + "target": { + "id": "postgres", + "details": { + "name": "attachment_taskId_idx", + "table": "attachment", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"attachment_taskId_idx\" ON \"public\".\"attachment\" (\"taskId\")", + "description": "create index \"attachment_taskId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"attachment_taskId_idx\"" + ], + "description": "ensure index \"attachment_taskId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"attachment_taskId_idx\"" + ], + "description": "verify index \"attachment_taskId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.attachment.attachment_taskId_fkey", + "label": "Add foreign key \"attachment_taskId_fkey\" on \"attachment\"", + "target": { + "id": "postgres", + "details": { + "name": "attachment_taskId_fkey", + "table": "attachment", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"attachment\"\nADD CONSTRAINT \"attachment_taskId_fkey\"\nFOREIGN KEY (\"taskId\")\nREFERENCES \"public\".\"task\" (\"id\")", + "description": "add FK \"attachment_taskId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "attachment_taskId_fkey", + "public", + "\"public\".\"attachment\"" + ], + "description": "ensure FK \"attachment_taskId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "attachment_taskId_fkey", + "public", + "\"public\".\"attachment\"" + ], + "description": "verify FK \"attachment_taskId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:35.498Z" + }, + { + "id": "16", + "space": "app", + "migration_name": "20260702T2237_project_settings", + "migration_hash": "sha256:ef33f89e4fc3899dc6b9ae51dea847054a029befb3742886fb8fcdf59fc0e6b7", + "origin_core_hash": "sha256:3527520ac103e0abecf2b605944f6435a659ee4c54e08909ab86e7fb1d42f8bf", + "destination_core_hash": "sha256:52d40a6dac828798beacb0df1bb7e5b596383ce7a7b6b8352f1903ce7b26e264", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:3527520ac103e0abecf2b605944f6435a659ee4c54e08909ab86e7fb1d42f8bf" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:59dd46584b014783f6f36a0155ba2f0015555a2e6d46de7201d1a120be5f3cb6" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:52d40a6dac828798beacb0df1bb7e5b596383ce7a7b6b8352f1903ce7b26e264" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:59dd46584b014783f6f36a0155ba2f0015555a2e6d46de7201d1a120be5f3cb6" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.project.settings", + "label": "Add column \"settings\" to \"project\"", + "target": { + "id": "postgres", + "details": { + "name": "settings", + "table": "project", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"project\" ADD COLUMN \"settings\" jsonb", + "description": "add column \"settings\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "project", + "settings" + ], + "description": "ensure column \"settings\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "project", + "settings" + ], + "description": "verify column \"settings\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "column.public.team.slug", + "label": "Add column \"slug\" to \"team\"", + "target": { + "id": "postgres", + "details": { + "name": "slug", + "table": "team", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"team\" ADD COLUMN \"slug\" text", + "description": "add column \"slug\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "team", + "slug" + ], + "description": "ensure column \"slug\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "team", + "slug" + ], + "description": "verify column \"slug\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:39.311Z" + }, + { + "id": "17", + "space": "app", + "migration_name": "20260702T2237_add_milestones", + "migration_hash": "sha256:a51b58cf7169d842126add05ed8b1f20462c74a91c4ad8724d63a5c8fc301098", + "origin_core_hash": "sha256:52d40a6dac828798beacb0df1bb7e5b596383ce7a7b6b8352f1903ce7b26e264", + "destination_core_hash": "sha256:f04ac4fcadc73bc59e9e779aa23d6dbd40ac4dfaa226f495639c0fcb6d36410a", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:52d40a6dac828798beacb0df1bb7e5b596383ce7a7b6b8352f1903ce7b26e264" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:59dd46584b014783f6f36a0155ba2f0015555a2e6d46de7201d1a120be5f3cb6" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:f04ac4fcadc73bc59e9e779aa23d6dbd40ac4dfaa226f495639c0fcb6d36410a" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "table.milestone", + "label": "Create table \"milestone\"", + "target": { + "id": "postgres", + "details": { + "name": "milestone", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "CREATE TABLE \"public\".\"milestone\" (\n \"dueAt\" timestamptz,\n \"id\" \"uuid\" NOT NULL,\n \"projectId\" \"uuid\" NOT NULL,\n \"title\" text NOT NULL,\n PRIMARY KEY (\"id\")\n)", + "params": [], + "description": "create table \"milestone\"" + } + ], + "summary": "Creates table \"milestone\"", + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"milestone\"" + ], + "description": "ensure table \"milestone\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"milestone\"" + ], + "description": "verify table \"milestone\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "column.public.task.milestoneId", + "label": "Add column \"milestoneId\" to \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "milestoneId", + "table": "task", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\" ADD COLUMN \"milestoneId\" \"uuid\"", + "description": "add column \"milestoneId\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "milestoneId" + ], + "description": "ensure column \"milestoneId\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "task", + "milestoneId" + ], + "description": "verify column \"milestoneId\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.milestone.milestone_projectId_idx", + "label": "Create index \"milestone_projectId_idx\" on \"milestone\"", + "target": { + "id": "postgres", + "details": { + "name": "milestone_projectId_idx", + "table": "milestone", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"milestone_projectId_idx\" ON \"public\".\"milestone\" (\"projectId\")", + "description": "create index \"milestone_projectId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"milestone_projectId_idx\"" + ], + "description": "ensure index \"milestone_projectId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"milestone_projectId_idx\"" + ], + "description": "verify index \"milestone_projectId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.task.task_milestoneId_idx", + "label": "Create index \"task_milestoneId_idx\" on \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task_milestoneId_idx", + "table": "task", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"task_milestoneId_idx\" ON \"public\".\"task\" (\"milestoneId\")", + "description": "create index \"task_milestoneId_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"task_milestoneId_idx\"" + ], + "description": "ensure index \"task_milestoneId_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"task_milestoneId_idx\"" + ], + "description": "verify index \"task_milestoneId_idx\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.milestone.milestone_projectId_fkey", + "label": "Add foreign key \"milestone_projectId_fkey\" on \"milestone\"", + "target": { + "id": "postgres", + "details": { + "name": "milestone_projectId_fkey", + "table": "milestone", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"milestone\"\nADD CONSTRAINT \"milestone_projectId_fkey\"\nFOREIGN KEY (\"projectId\")\nREFERENCES \"public\".\"project\" (\"id\")", + "description": "add FK \"milestone_projectId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "milestone_projectId_fkey", + "public", + "\"public\".\"milestone\"" + ], + "description": "ensure FK \"milestone_projectId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "milestone_projectId_fkey", + "public", + "\"public\".\"milestone\"" + ], + "description": "verify FK \"milestone_projectId_fkey\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "foreignKey.task.task_milestoneId_fkey", + "label": "Add foreign key \"task_milestoneId_fkey\" on \"task\"", + "target": { + "id": "postgres", + "details": { + "name": "task_milestoneId_fkey", + "table": "task", + "schema": "public", + "objectType": "foreignKey" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"task\"\nADD CONSTRAINT \"task_milestoneId_fkey\"\nFOREIGN KEY (\"milestoneId\")\nREFERENCES \"public\".\"milestone\" (\"id\")", + "description": "add FK \"task_milestoneId_fkey\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_milestoneId_fkey", + "public", + "\"public\".\"task\"" + ], + "description": "ensure FK \"task_milestoneId_fkey\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "task_milestoneId_fkey", + "public", + "\"public\".\"task\"" + ], + "description": "verify FK \"task_milestoneId_fkey\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:43.250Z" + }, + { + "id": "18", + "space": "app", + "migration_name": "20260702T2237_hot_path_indexes", + "migration_hash": "sha256:f0ad59c46a17df8542a0cdaff0d319709ec9e23c440619a1ab1616474b4422ea", + "origin_core_hash": "sha256:f04ac4fcadc73bc59e9e779aa23d6dbd40ac4dfaa226f495639c0fcb6d36410a", + "destination_core_hash": "sha256:b5279a2c7c69ffd9ecb79a6020475803003b5b61b9d5b43dd9713d68ae9ee390", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:f04ac4fcadc73bc59e9e779aa23d6dbd40ac4dfaa226f495639c0fcb6d36410a" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:b5279a2c7c69ffd9ecb79a6020475803003b5b61b9d5b43dd9713d68ae9ee390" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "index.comment.comment_taskId_createdAt_idx", + "label": "Create index \"comment_taskId_createdAt_idx\" on \"comment\"", + "target": { + "id": "postgres", + "details": { + "name": "comment_taskId_createdAt_idx", + "table": "comment", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"comment_taskId_createdAt_idx\" ON \"public\".\"comment\" (\"taskId\", \"createdAt\")", + "description": "create index \"comment_taskId_createdAt_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"comment_taskId_createdAt_idx\"" + ], + "description": "ensure index \"comment_taskId_createdAt_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"comment_taskId_createdAt_idx\"" + ], + "description": "verify index \"comment_taskId_createdAt_idx\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:47.123Z" + }, + { + "id": "19", + "space": "app", + "migration_name": "20260702T2237_user_presence", + "migration_hash": "sha256:a5b94641e8b0d5c83057404c09bf6f95f6196a8bb8dee61d67a24d73e4925b1c", + "origin_core_hash": "sha256:b5279a2c7c69ffd9ecb79a6020475803003b5b61b9d5b43dd9713d68ae9ee390", + "destination_core_hash": "sha256:e9410555e0cb4878c0132cc3822e76422e66b8b855259878c2fb34d52829dacb", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:b5279a2c7c69ffd9ecb79a6020475803003b5b61b9d5b43dd9713d68ae9ee390" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "lastSeenAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + }, + "lastSeenAt": { + "column": "lastSeenAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "slug" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "lastSeenAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "actorId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:e9410555e0cb4878c0132cc3822e76422e66b8b855259878c2fb34d52829dacb" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "column.public.user.lastSeenAt", + "label": "Add column \"lastSeenAt\" to \"user\"", + "target": { + "id": "postgres", + "details": { + "name": "lastSeenAt", + "table": "user", + "schema": "public", + "objectType": "column" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"user\" ADD COLUMN \"lastSeenAt\" timestamptz", + "description": "add column \"lastSeenAt\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "lastSeenAt" + ], + "description": "ensure column \"lastSeenAt\" is missing" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"information_schema\".\"columns\" WHERE (\"table_schema\" = $1 AND \"table_name\" = $2 AND \"column_name\" = $3)) AS \"result\"", + "params": [ + "public", + "user", + "lastSeenAt" + ], + "description": "verify column \"lastSeenAt\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "unique.team.team_slug_key", + "label": "Add unique constraint on \"team\" (slug)", + "target": { + "id": "postgres", + "details": { + "name": "team_slug_key", + "table": "team", + "schema": "public", + "objectType": "unique" + } + }, + "execute": [ + { + "sql": "ALTER TABLE \"public\".\"team\" ADD CONSTRAINT \"team_slug_key\" UNIQUE (\"slug\")", + "description": "add unique constraint \"team_slug_key\"" + } + ], + "precheck": [ + { + "sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "team_slug_key", + "public", + "\"public\".\"team\"" + ], + "description": "ensure constraint \"team_slug_key\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", + "params": [ + "team_slug_key", + "public", + "\"public\".\"team\"" + ], + "description": "verify constraint \"team_slug_key\" exists" + } + ], + "operationClass": "additive" + }, + { + "id": "index.activity_log.activity_log_actorId_createdAt_idx", + "label": "Create index \"activity_log_actorId_createdAt_idx\" on \"activity_log\"", + "target": { + "id": "postgres", + "details": { + "name": "activity_log_actorId_createdAt_idx", + "table": "activity_log", + "schema": "public", + "objectType": "index" + } + }, + "execute": [ + { + "sql": "CREATE INDEX \"activity_log_actorId_createdAt_idx\" ON \"public\".\"activity_log\" (\"actorId\", \"createdAt\")", + "description": "create index \"activity_log_actorId_createdAt_idx\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log_actorId_createdAt_idx\"" + ], + "description": "ensure index \"activity_log_actorId_createdAt_idx\" does not exist" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log_actorId_createdAt_idx\"" + ], + "description": "verify index \"activity_log_actorId_createdAt_idx\" exists" + } + ], + "operationClass": "additive" + } + ], + "created_at": "2026-07-02T22:37:51.026Z" + }, + { + "id": "20", + "space": "app", + "migration_name": "20260702T2237_retire_activity_log", + "migration_hash": "sha256:0f963a382a7cdbc8bb0f1a2f31148cbb78ec025d10c1a17c5ed67fa694315a98", + "origin_core_hash": "sha256:e9410555e0cb4878c0132cc3822e76422e66b8b855259878c2fb34d52829dacb", + "destination_core_hash": "sha256:811cea82e78e9812ffc3f4fc824f08655fa6a58e10118fc9d7a71e5bd2da0e57", + "contract_json_before": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + }, + "activity_log": { + "model": "ActivityLog", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "lastSeenAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + }, + "lastSeenAt": { + "column": "lastSeenAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "activities": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "actorId" + ] + }, + "to": { + "model": "ActivityLog", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "ActivityLog": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "kind": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "actorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "payload": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "activity_log", + "fields": { + "id": { + "column": "id" + }, + "kind": { + "column": "kind" + }, + "actorId": { + "column": "actorId" + }, + "payload": { + "column": "payload" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "actor": { + "on": { + "localFields": [ + "actorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "slug" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "lastSeenAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "activity_log": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "kind": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "actorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "payload": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "actorId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "actorId" + ], + "tableName": "activity_log", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:e9410555e0cb4878c0132cc3822e76422e66b8b855259878c2fb34d52829dacb" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "activity_log", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:bfe9551783f00b0209cf787798486b466f012ecf93cc306d89d70c77a0d0ec56" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "contract_json_after": { + "meta": {}, + "roots": { + "tag": { + "model": "Tag", + "namespace": "public" + }, + "task": { + "model": "Task", + "namespace": "public" + }, + "team": { + "model": "Team", + "namespace": "public" + }, + "user": { + "model": "User", + "namespace": "public" + }, + "comment": { + "model": "Comment", + "namespace": "public" + }, + "project": { + "model": "Project", + "namespace": "public" + }, + "task_tag": { + "model": "TaskTag", + "namespace": "public" + }, + "milestone": { + "model": "Milestone", + "namespace": "public" + }, + "attachment": { + "model": "Attachment", + "namespace": "public" + } + }, + "domain": { + "namespaces": { + "public": { + "enum": { + "Priority": { + "codecId": "pg/text@1", + "members": [ + { + "name": "low", + "value": "low" + }, + { + "name": "medium", + "value": "medium" + }, + { + "name": "high", + "value": "high" + } + ] + }, + "TaskStatus": { + "codecId": "pg/text@1", + "members": [ + { + "name": "todo", + "value": "todo" + }, + { + "name": "in_progress", + "value": "in_progress" + }, + { + "name": "done", + "value": "done" + } + ] + } + }, + "models": { + "Tag": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "label": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + } + }, + "storage": { + "table": "tag", + "fields": { + "id": { + "column": "id" + }, + "label": { + "column": "label" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "tagId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Task": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "status": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "TaskStatus", + "namespaceId": "public" + } + }, + "priority": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false, + "valueSet": { + "plane": "domain", + "entityKind": "enum", + "entityName": "Priority", + "namespaceId": "public" + } + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "milestoneId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + } + }, + "storage": { + "table": "task", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "status": { + "column": "status" + }, + "priority": { + "column": "priority" + }, + "createdAt": { + "column": "createdAt" + }, + "projectId": { + "column": "projectId" + }, + "milestoneId": { + "column": "milestoneId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tags": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "TaskTag", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestone": { + "on": { + "localFields": [ + "milestoneId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "attachments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "taskId" + ] + }, + "to": { + "model": "Attachment", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Team": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "slug": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "team", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "slug": { + "column": "slug" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "members": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "teamId" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "User": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "bio": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "email": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "teamId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": true + }, + "avatarUrl": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "lastSeenAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + } + }, + "storage": { + "table": "user", + "fields": { + "id": { + "column": "id" + }, + "bio": { + "column": "bio" + }, + "name": { + "column": "name" + }, + "email": { + "column": "email" + }, + "teamId": { + "column": "teamId" + }, + "avatarUrl": { + "column": "avatarUrl" + }, + "createdAt": { + "column": "createdAt" + }, + "lastSeenAt": { + "column": "lastSeenAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "team": { + "on": { + "localFields": [ + "teamId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Team", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "comments": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "authorId" + ] + }, + "to": { + "model": "Comment", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "projects": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "ownerId" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "Comment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "body": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "authorId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "comment", + "fields": { + "id": { + "column": "id" + }, + "body": { + "column": "body" + }, + "taskId": { + "column": "taskId" + }, + "authorId": { + "column": "authorId" + }, + "createdAt": { + "column": "createdAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "author": { + "on": { + "localFields": [ + "authorId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Project": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "name": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "ownerId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "settings": { + "type": { + "kind": "scalar", + "codecId": "pg/jsonb@1" + }, + "nullable": true + }, + "createdAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + }, + "deletedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "description": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": true + } + }, + "storage": { + "table": "project", + "fields": { + "id": { + "column": "id" + }, + "name": { + "column": "name" + }, + "ownerId": { + "column": "ownerId" + }, + "settings": { + "column": "settings" + }, + "createdAt": { + "column": "createdAt" + }, + "deletedAt": { + "column": "deletedAt" + }, + "description": { + "column": "description" + } + }, + "namespaceId": "public" + }, + "relations": { + "owner": { + "on": { + "localFields": [ + "ownerId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "User", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "milestones": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "projectId" + ] + }, + "to": { + "model": "Milestone", + "namespace": "public" + }, + "cardinality": "1:N" + } + } + }, + "TaskTag": { + "fields": { + "tagId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "task_tag", + "fields": { + "tagId": { + "column": "tagId" + }, + "taskId": { + "column": "taskId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tag": { + "on": { + "localFields": [ + "tagId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Tag", + "namespace": "public" + }, + "cardinality": "N:1" + }, + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Milestone": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "dueAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": true + }, + "title": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "projectId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + } + }, + "storage": { + "table": "milestone", + "fields": { + "id": { + "column": "id" + }, + "dueAt": { + "column": "dueAt" + }, + "title": { + "column": "title" + }, + "projectId": { + "column": "projectId" + } + }, + "namespaceId": "public" + }, + "relations": { + "tasks": { + "on": { + "localFields": [ + "id" + ], + "targetFields": [ + "milestoneId" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "1:N" + }, + "project": { + "on": { + "localFields": [ + "projectId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Project", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + }, + "Attachment": { + "fields": { + "id": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "taskId": { + "type": { + "kind": "scalar", + "codecId": "pg/uuid@1" + }, + "nullable": false + }, + "fileName": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "mimeType": { + "type": { + "kind": "scalar", + "codecId": "pg/text@1" + }, + "nullable": false + }, + "sizeBytes": { + "type": { + "kind": "scalar", + "codecId": "pg/int8@1" + }, + "nullable": false + }, + "uploadedAt": { + "type": { + "kind": "scalar", + "codecId": "pg/timestamptz@1" + }, + "nullable": false + } + }, + "storage": { + "table": "attachment", + "fields": { + "id": { + "column": "id" + }, + "taskId": { + "column": "taskId" + }, + "fileName": { + "column": "fileName" + }, + "mimeType": { + "column": "mimeType" + }, + "sizeBytes": { + "column": "sizeBytes" + }, + "uploadedAt": { + "column": "uploadedAt" + } + }, + "namespaceId": "public" + }, + "relations": { + "task": { + "on": { + "localFields": [ + "taskId" + ], + "targetFields": [ + "id" + ] + }, + "to": { + "model": "Task", + "namespace": "public" + }, + "cardinality": "N:1" + } + } + } + } + } + } + }, + "target": "postgres", + "storage": { + "types": { + "Uuid": { + "kind": "codec-instance", + "codecId": "pg/uuid@1", + "nativeType": "uuid" + } + }, + "namespaces": { + "public": { + "id": "public", + "kind": "postgres-schema", + "entries": { + "table": { + "tag": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "label": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "label" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "task": { + "checks": [ + { + "name": "task_priority_check", + "column": "priority", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + } + }, + { + "name": "task_status_check", + "column": "status", + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + } + } + ], + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "status": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "todo" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "TaskStatus", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "priority": { + "codecId": "pg/text@1", + "default": { + "kind": "literal", + "value": "low" + }, + "nullable": false, + "valueSet": { + "plane": "storage", + "entityKind": "valueSet", + "entityName": "Priority", + "namespaceId": "public" + }, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "milestoneId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + } + }, + "indexes": [ + { + "columns": [ + "projectId", + "dueAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "milestoneId" + ], + "tableName": "task", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "team": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "slug": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "slug" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [] + }, + "user": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "bio": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "email": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "teamId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": true, + "nativeType": "uuid" + }, + "avatarUrl": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "lastSeenAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + } + }, + "indexes": [], + "uniques": [ + { + "columns": [ + "email" + ] + } + ], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "teamId" + ], + "tableName": "user", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "team", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "comment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "body": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "authorId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId", + "createdAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "authorId" + ], + "tableName": "comment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "project": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "name": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "ownerId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "settings": { + "codecId": "pg/jsonb@1", + "nullable": true, + "nativeType": "jsonb" + }, + "createdAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + }, + "deletedAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "description": { + "codecId": "pg/text@1", + "nullable": true, + "nativeType": "text" + } + }, + "indexes": [ + { + "columns": [ + "deletedAt" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "ownerId" + ], + "tableName": "project", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "user", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "task_tag": { + "columns": { + "tagId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "taskId", + "tagId" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + }, + { + "index": true, + "source": { + "columns": [ + "tagId" + ], + "tableName": "task_tag", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "tag", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "milestone": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "dueAt": { + "codecId": "pg/timestamptz@1", + "nullable": true, + "nativeType": "timestamptz" + }, + "title": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "projectId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + } + }, + "indexes": [], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "projectId" + ], + "tableName": "milestone", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "project", + "namespaceId": "public" + }, + "constraint": true + } + ] + }, + "attachment": { + "columns": { + "id": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "taskId": { + "codecId": "pg/uuid@1", + "typeRef": "Uuid", + "nullable": false, + "nativeType": "uuid" + }, + "fileName": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "mimeType": { + "codecId": "pg/text@1", + "nullable": false, + "nativeType": "text" + }, + "sizeBytes": { + "codecId": "pg/int8@1", + "nullable": false, + "nativeType": "int8" + }, + "uploadedAt": { + "codecId": "pg/timestamptz@1", + "default": { + "kind": "function", + "expression": "now()" + }, + "nullable": false, + "nativeType": "timestamptz" + } + }, + "indexes": [ + { + "columns": [ + "taskId" + ] + } + ], + "uniques": [], + "primaryKey": { + "columns": [ + "id" + ] + }, + "foreignKeys": [ + { + "index": true, + "source": { + "columns": [ + "taskId" + ], + "tableName": "attachment", + "namespaceId": "public" + }, + "target": { + "columns": [ + "id" + ], + "tableName": "task", + "namespaceId": "public" + }, + "constraint": true + } + ] + } + }, + "valueSet": { + "Priority": { + "kind": "valueSet", + "values": [ + "low", + "medium", + "high" + ] + }, + "TaskStatus": { + "kind": "valueSet", + "values": [ + "todo", + "in_progress", + "done" + ] + } + } + } + } + }, + "storageHash": "sha256:811cea82e78e9812ffc3f4fc824f08655fa6a58e10118fc9d7a71e5bd2da0e57" + }, + "execution": { + "mutations": { + "defaults": [ + { + "ref": { + "table": "attachment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "comment", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "milestone", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "project", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "tag", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "task", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "team", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + }, + { + "ref": { + "table": "user", + "column": "id", + "namespace": "public" + }, + "onCreate": { + "id": "uuidv4", + "kind": "generator" + } + } + ] + }, + "executionHash": "sha256:eda51dced8492164408e70b7a9db6fb1b8cab340c078ea050b2dcbc84dacfab4" + }, + "_generated": { + "message": "This file is automatically generated by \"prisma-next contract emit\".", + "warning": "⚠️ GENERATED FILE - DO NOT EDIT", + "regenerate": "To regenerate, run: prisma-next contract emit" + }, + "profileHash": "sha256:9c8aa3114e84ed3b7ea2bd57526d9c2e1bf7c5292be694e9d3801f566fda7ccb", + "capabilities": { + "sql": { + "enums": true, + "lateral": true, + "returning": true, + "scalarList": true, + "defaultInInsert": true + }, + "postgres": { + "limit": true, + "jsonAgg": true, + "lateral": true, + "orderBy": true, + "returning": true, + "distinctOn": true + } + }, + "targetFamily": "sql", + "schemaVersion": "1", + "extensionPacks": {} + }, + "operations": [ + { + "id": "dropTable.activity_log", + "label": "Drop table \"activity_log\"", + "target": { + "id": "postgres", + "details": { + "name": "activity_log", + "schema": "public", + "objectType": "table" + } + }, + "execute": [ + { + "sql": "DROP TABLE \"public\".\"activity_log\"", + "description": "drop table \"activity_log\"" + } + ], + "precheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log\"" + ], + "description": "ensure table \"activity_log\" exists" + } + ], + "postcheck": [ + { + "sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", + "params": [ + "\"public\".\"activity_log\"" + ], + "description": "verify table \"activity_log\" does not exist" + } + ], + "operationClass": "destructive" + } + ], + "created_at": "2026-07-02T22:37:54.866Z" + } + ] +} diff --git a/demo/ppg-dev/seed-database.ts b/demo/ppg-dev/seed-database.ts index 7801a97e..42f6d980 100644 --- a/demo/ppg-dev/seed-database.ts +++ b/demo/ppg-dev/seed-database.ts @@ -1,5 +1,7 @@ import postgres from "postgres"; +import { seedPrismaNextMigrations } from "./seed-migrations"; + type OrganizationSeedRow = { created_at: Date; id: string; @@ -611,6 +613,8 @@ export async function seedDatabase(connectionString: string): Promise { from generate_series(1, 100) as series(i) `); }); + + await seedPrismaNextMigrations(sql); } finally { await sql.end({ timeout: 5 }); } diff --git a/demo/ppg-dev/seed-migrations.ts b/demo/ppg-dev/seed-migrations.ts new file mode 100644 index 00000000..0bfbd161 --- /dev/null +++ b/demo/ppg-dev/seed-migrations.ts @@ -0,0 +1,311 @@ +import type postgres from "postgres"; + +import fixtureJson from "./fixtures/prisma-contract-migrations.json"; + +/** + * Replays the Prisma Next migration history captured from the + * migrations-showcase example (see prisma-next repo, + * examples/migrations-showcase) into the demo database: + * + * - restores `prisma_contract.marker` / `prisma_contract.ledger` plus the + * content-addressed `prisma_contract.contract` store (one row per + * distinct contract, keyed by its storage hash), and + * - re-executes every migration operation's SQL in ledger order so the + * live schema matches the migration history exactly. + * + * Studio's Migrations view detects the ledger table and renders the + * visual diff per migration by joining the store onto the ledger's + * origin/destination hash columns — both edge endpoints are direct + * lookups. + */ + +interface FixtureMarkerRow { + space: string; + core_hash: string; + profile_hash: string; + contract_json: unknown; + canonical_version: number | null; + app_tag: string | null; + meta: unknown; + invariants: string[]; + updated_at: string; +} + +interface FixtureOperationStep { + sql: string; + params?: unknown[]; +} + +interface FixtureOperation { + id: string; + label: string; + operationClass: string; + execute?: FixtureOperationStep[]; +} + +interface FixtureLedgerRow { + id: number; + space: string; + migration_name: string; + migration_hash: string; + origin_core_hash: string | null; + destination_core_hash: string; + contract_json_before: unknown; + contract_json_after: unknown; + operations: FixtureOperation[]; + created_at: string; +} + +interface MigrationsFixture { + generatedAt: string; + marker: FixtureMarkerRow[]; + ledger: FixtureLedgerRow[]; +} + +// Statically imported so every bundling path (tsx, `bun build` for the +// local bundle, and the Compute deploy build) inlines the fixture into +// the artifact instead of depending on a file next to the bundle. +function loadFixture(): MigrationsFixture { + return fixtureJson as unknown as MigrationsFixture; +} + +export async function seedPrismaNextMigrations( + sql: postgres.Sql, +): Promise { + const fixture = loadFixture(); + + await sql.unsafe(`create schema if not exists prisma_contract`); + await sql.unsafe(` + create table if not exists prisma_contract.marker ( + space text primary key default 'app', + core_hash text not null, + profile_hash text not null, + contract_json jsonb, + canonical_version int, + updated_at timestamptz not null default now(), + app_tag text, + meta jsonb not null default '{}', + invariants text[] not null default '{}' + ) + `); + await sql.unsafe(` + create table if not exists prisma_contract.ledger ( + id bigserial primary key, + created_at timestamptz not null default now(), + space text not null, + migration_name text not null, + migration_hash text not null, + origin_core_hash text, + origin_profile_hash text, + destination_core_hash text not null, + destination_profile_hash text, + operations jsonb not null + ) + `); + await sql.unsafe(` + create table if not exists prisma_contract.contract ( + core_hash text not null primary key, + created_at timestamptz not null default now(), + contract_json jsonb not null + ) + `); + + await upgradeLegacyLedger(sql); + + const [{ count }] = (await sql.unsafe( + `select count(*)::int as count from prisma_contract.ledger`, + )) as unknown as [{ count: number }]; + + if (count > 0) { + return; + } + + // One transaction for the whole replay: a partial failure would leave + // ledger rows behind, and the count-based idempotency guard would then + // skip reseeding forever on a persistent volume. Statements go through + // `tx.unsafe` with bound params because this postgres.js version's + // `TransactionSql` type is an `Omit` that loses the + // template-tag call signature. + await sql.begin(async (tx) => { + for (const row of fixture.ledger) { + for (const operation of row.operations) { + for (const step of operation.execute ?? []) { + await tx.unsafe(step.sql, (step.params ?? []) as never[]); + } + } + + // The fixture predates the content-addressed store and carries both + // bookends per row; only the after-state is written — keyed by the + // destination hash, deduplicated on conflict — and every non-baseline + // origin hash is some predecessor's destination, so both endpoints of + // every edge resolve. + if (row.contract_json_after !== null) { + await tx.unsafe( + `insert into prisma_contract.contract (core_hash, created_at, contract_json) + values ($1, $2, $3::jsonb) + on conflict (core_hash) do nothing`, + [ + row.destination_core_hash, + row.created_at, + JSON.stringify(row.contract_json_after), + ] as never[], + ); + } + + await tx.unsafe( + `insert into prisma_contract.ledger ( + created_at, space, migration_name, migration_hash, + origin_core_hash, destination_core_hash, operations + ) values ($1, $2, $3, $4, $5, $6, $7::jsonb)`, + [ + row.created_at, + row.space, + row.migration_name, + row.migration_hash, + row.origin_core_hash, + row.destination_core_hash, + JSON.stringify(row.operations), + ] as never[], + ); + } + + for (const row of fixture.marker) { + await tx.unsafe( + `insert into prisma_contract.marker ( + space, core_hash, profile_hash, contract_json, canonical_version, + updated_at, app_tag, meta, invariants + ) values ($1, $2, $3, $4::jsonb, $5, $6, $7, $8::jsonb, $9::text[]) + on conflict (space) do nothing`, + [ + row.space, + row.core_hash, + row.profile_hash, + row.contract_json === null ? null : JSON.stringify(row.contract_json), + row.canonical_version, + row.updated_at, + row.app_tag, + JSON.stringify(row.meta ?? {}), + row.invariants, + ] as never[], + ); + } + + await seedShowcaseRows(tx); + }); +} + +/** + * Upgrades a demo database seeded by an older shape so a persistent + * volume converges on the hash-keyed contract store: + * + * - a contract table keyed by `ledger_id` (the interim 1:1 design) is + * re-keyed by each row's destination hash, and + * - a ledger still carrying the legacy `contract_json_before/after` + * columns has its after-states moved into the store and the bookend + * columns dropped. + */ +async function upgradeLegacyLedger(sql: postgres.Sql): Promise { + const ledgerIdKeyed = (await sql.unsafe(` + select 1 + from information_schema.columns + where table_schema = 'prisma_contract' + and table_name = 'contract' + and column_name = 'ledger_id' + `)) as unknown as unknown[]; + + if (ledgerIdKeyed.length > 0) { + await sql.unsafe(` + create table prisma_contract.contract_rekeyed ( + core_hash text not null primary key, + created_at timestamptz not null default now(), + contract_json jsonb not null + ) + `); + await sql.unsafe(` + insert into prisma_contract.contract_rekeyed (core_hash, created_at, contract_json) + select l.destination_core_hash, c.created_at, c.contract_json + from prisma_contract.contract c + join prisma_contract.ledger l on l.id = c.ledger_id + on conflict (core_hash) do nothing + `); + await sql.unsafe(`drop table prisma_contract.contract`); + await sql.unsafe( + `alter table prisma_contract.contract_rekeyed rename to contract`, + ); + } + + const legacyColumns = (await sql.unsafe(` + select 1 + from information_schema.columns + where table_schema = 'prisma_contract' + and table_name = 'ledger' + and column_name = 'contract_json_after' + `)) as unknown as unknown[]; + + if (legacyColumns.length === 0) { + return; + } + + await sql.unsafe(` + insert into prisma_contract.contract (core_hash, created_at, contract_json) + select destination_core_hash, created_at, contract_json_after + from prisma_contract.ledger + where contract_json_after is not null + on conflict (core_hash) do nothing + `); + await sql.unsafe( + `alter table prisma_contract.ledger drop column if exists contract_json_before`, + ); + await sql.unsafe( + `alter table prisma_contract.ledger drop column if exists contract_json_after`, + ); +} + +/** + * A few rows for the tables created by the replayed migrations so the + * demo tables aren't empty when browsed. Receives the replay transaction + * so the showcase rows commit atomically with the history. + */ +async function seedShowcaseRows(sql: postgres.TransactionSql): Promise { + await sql.unsafe(` + with team as ( + insert into "team" (id, name, slug) + values (gen_random_uuid(), 'Aurora Core', 'aurora-core') + returning id + ), + users as ( + insert into "user" (id, email, name, "avatarUrl", bio, "teamId", "lastSeenAt") + select gen_random_uuid(), email, name, null, bio, team.id, now() + from team, + (values + ('ada@aurora.dev', 'Ada Lovelace', 'Loves invariants.'), + ('grace@aurora.dev', 'Grace Hopper', 'Ship it.'), + ('edsger@aurora.dev', 'Edsger Dijkstra', 'Simplicity advocate.') + ) as seed(email, name, bio) + returning id, email + ), + project as ( + insert into "project" (id, name, description, "ownerId", settings) + select gen_random_uuid(), 'Launch Aurora', 'The Q3 flagship launch.', users.id, '{"visibility":"internal"}'::jsonb + from users + where users.email = 'ada@aurora.dev' + returning id + ), + milestone as ( + insert into "milestone" (id, "projectId", title, "dueAt") + select gen_random_uuid(), project.id, 'Public beta', now() + interval '21 days' + from project + returning id, "projectId" + ) + insert into "task" (id, "projectId", title, priority, status, "dueAt", "milestoneId") + select gen_random_uuid(), milestone."projectId", seed.title, seed.priority, seed.status, + now() + (seed.due_days || ' days')::interval, milestone.id + from milestone, + (values + ('Design the migration timeline', 'high', 'in_progress', '3'), + ('Ship visual schema diffs', 'high', 'todo', '7'), + ('Polish FigJam-style cards', 'medium', 'todo', '10'), + ('Record the launch video', 'low', 'done', '1') + ) as seed(title, priority, status, due_days) + `); +} diff --git a/package.json b/package.json index 344d073c..0aaa9054 100644 --- a/package.json +++ b/package.json @@ -197,6 +197,7 @@ "clsx": "2.1.1", "cmdk": "1.1.1", "dayjs": "1.11.19", + "diff": "8.0.2", "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "2.29.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d24d52f8..d7350ebf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -193,6 +193,9 @@ devDependencies: dayjs: specifier: 1.11.19 version: 1.11.19 + diff: + specifier: 8.0.2 + version: 8.0.2 eslint: specifier: 8.57.0 version: 8.57.0 @@ -4172,6 +4175,11 @@ packages: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} dev: true + /diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + engines: {node: '>=0.3.1'} + dev: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} diff --git a/scripts/compute-preview/compute-preview-deploy.mjs b/scripts/compute-preview/compute-preview-deploy.mjs index 4ce4c48c..e0785b17 100644 --- a/scripts/compute-preview/compute-preview-deploy.mjs +++ b/scripts/compute-preview/compute-preview-deploy.mjs @@ -5,9 +5,9 @@ import { appendFileSync } from "node:fs"; import { promisify } from "node:util"; import { - PREVIEW_PROJECT_NAME, findNamedProject, findNamedService, + PREVIEW_PROJECT_NAME, sanitizeComputeServiceName, } from "./compute-preview-utils.mjs"; @@ -41,13 +41,30 @@ async function main() { service.id, ]); + // Newer Compute CLI payloads surface the endpoint as `appEndpointDomain` + // (on both the deploy result and `services show`) instead of the older + // `serviceEndpointDomain`; fall back through the known shapes so the PR + // comment step always receives a URL. + const serviceUrl = + deployResult.serviceEndpointDomain ?? + deployResult.appEndpointDomain ?? + (await showService(service.id)).appEndpointDomain; + + if (!serviceUrl) { + throw new Error( + `Compute deploy for service ${service.id} returned no endpoint domain ` + + "(checked serviceEndpointDomain, appEndpointDomain, and services show); " + + "cannot report a preview URL.", + ); + } + const result = { branchName, projectId: project.id, region: project.defaultRegion ?? "eu-west-3", serviceId: service.id, serviceName, - serviceUrl: deployResult.serviceEndpointDomain, + serviceUrl, versionId: deployResult.versionId, versionUrl: deployResult.versionEndpointDomain, }; @@ -56,6 +73,10 @@ async function main() { process.stdout.write(`${JSON.stringify(result, null, 2)}\n`); } +async function showService(serviceId) { + return await runComputeJson(["services", "show", serviceId]); +} + async function resolveProject(projectName) { const projects = await runComputeJson(["projects", "list"]); const project = findNamedProject(projects, projectName); @@ -139,7 +160,9 @@ function writeOutputs(result) { preview_service_url: result.serviceUrl, preview_version_id: result.versionId, preview_version_url: result.versionUrl, - }).map(([key, value]) => `${key}=${value}`); + }) + .filter(([, value]) => value != null) + .map(([key, value]) => `${key}=${value}`); appendFileSync(outputPath, `${lines.join("\n")}\n`); } diff --git a/ui/hooks/nuqs.ts b/ui/hooks/nuqs.ts index 20e922e7..d68b1a14 100644 --- a/ui/hooks/nuqs.ts +++ b/ui/hooks/nuqs.ts @@ -18,6 +18,7 @@ export * from "nuqs"; export type StateKey = | "aggregations" + | "migration" | "pageIndex" | "pageSize" | "pin" diff --git a/ui/hooks/react-query.ts b/ui/hooks/react-query.ts index 346fc44b..ef752acb 100644 --- a/ui/hooks/react-query.ts +++ b/ui/hooks/react-query.ts @@ -9,6 +9,8 @@ type MutationKey = type QueryKey = | [] // all | ["introspection"] + | ["prisma-next-migrations", "contract-table", boolean] + | ["prisma-next-migrations-probe"] | ["stream-details", string] | ["stream-routing-keys", string, "stream", string, "prefix", string] | ["streams-server-details", string] diff --git a/ui/hooks/use-migrations.test.ts b/ui/hooks/use-migrations.test.ts new file mode 100644 index 00000000..0eccd3c1 --- /dev/null +++ b/ui/hooks/use-migrations.test.ts @@ -0,0 +1,144 @@ +import { describe, expect, it } from "vitest"; + +import { parseLedgerProbeRows, parseLedgerRows } from "./use-migrations"; + +function ledgerRow( + overrides: Record, +): Record { + return { + id: 1, + space: "app", + migration_name: "20260702T2236_init_users", + migration_hash: "sha256:mig", + origin_core_hash: null, + destination_core_hash: "sha256:c1", + contract_json_before: null, + contract_json_after: { marker: "after" }, + operations: [], + created_at: "2026-07-02T22:36:00.000Z", + ...overrides, + }; +} + +describe("parseLedgerRows", () => { + it("parses rows into migrations sorted by ledger id", () => { + const migrations = parseLedgerRows([ + ledgerRow({ id: 2, migration_name: "20260702T2236_add_projects" }), + ledgerRow({ id: 1 }), + ]); + + expect(migrations.map((migration) => migration.id)).toEqual([1, 2]); + expect(migrations[0]?.displayName).toBe("init users"); + expect(migrations[1]?.displayName).toBe("add projects"); + expect(migrations[0]?.appliedAt).toBeInstanceOf(Date); + }); + + it("labels synthesised applies without a migration name", () => { + const migrations = parseLedgerRows([ledgerRow({ migration_name: "" })]); + + expect(migrations[0]?.displayName).toBe("Schema sync"); + }); + + it("parses jsonb columns that arrive as strings", () => { + const migrations = parseLedgerRows([ + ledgerRow({ + contract_json_after: JSON.stringify({ marker: "after" }), + operations: JSON.stringify([ + { + id: "op", + label: "Create table", + operationClass: "additive", + execute: [{ sql: "CREATE TABLE x ()" }], + }, + ]), + }), + ]); + + expect(migrations[0]?.contractAfter).toEqual({ marker: "after" }); + expect(migrations[0]?.operations[0]?.statements).toEqual([ + "CREATE TABLE x ()", + ]); + }); + + it("flags migrations containing destructive operations", () => { + const migrations = parseLedgerRows([ + ledgerRow({ + operations: [ + { + id: "op", + label: "Drop column", + operationClass: "destructive", + execute: [{ sql: "ALTER TABLE t DROP COLUMN c" }], + }, + ], + }), + ]); + + expect(migrations[0]?.isDestructive).toBe(true); + }); + + it("takes both endpoint snapshots directly from the hash joins", () => { + // The query joins the content-addressed contract store onto + // origin_core_hash and destination_core_hash — no client-side chain + // reconstruction. + const migrations = parseLedgerRows([ + ledgerRow({ id: 1, contract_json_after: { state: "c1" } }), + ledgerRow({ + id: 2, + origin_core_hash: "sha256:c1", + destination_core_hash: "sha256:c2", + contract_json_before: { state: "c1" }, + contract_json_after: { state: "c2" }, + }), + ]); + + expect(migrations[0]?.contractBefore).toBeNull(); + expect(migrations[1]?.contractBefore).toEqual({ state: "c1" }); + expect(migrations[1]?.contractAfter).toEqual({ state: "c2" }); + }); + + it("treats an unresolved origin hash as an unknown before-state", () => { + // Origin hash present but no contract row joined (drift, or the + // predecessor carried no snapshot) — the join yields null. + const migrations = parseLedgerRows([ + ledgerRow({ + id: 2, + origin_core_hash: "sha256:unknown", + destination_core_hash: "sha256:c2", + contract_json_before: null, + contract_json_after: { state: "c2" }, + }), + ]); + + expect(migrations[0]?.contractBefore).toBeNull(); + }); + + it("leaves a baseline migration's before-snapshot empty", () => { + const migrations = parseLedgerRows([ledgerRow({})]); + + expect(migrations[0]?.contractBefore).toBeNull(); + expect(migrations[0]?.fromHash).toBeNull(); + }); + + it("skips rows without a usable id", () => { + const migrations = parseLedgerRows([ledgerRow({}), { id: "not-a-number" }]); + + expect(migrations).toHaveLength(1); + }); +}); + +describe("parseLedgerProbeRows", () => { + it("accepts driver-flavored truthy values", () => { + expect(parseLedgerProbeRows([{ has_rows: true }])).toBe(true); + expect(parseLedgerProbeRows([{ has_rows: "t" }])).toBe(true); + expect(parseLedgerProbeRows([{ has_rows: "true" }])).toBe(true); + expect(parseLedgerProbeRows([{ has_rows: 1 }])).toBe(true); + }); + + it("treats false, missing, and malformed results as no history", () => { + expect(parseLedgerProbeRows([{ has_rows: false }])).toBe(false); + expect(parseLedgerProbeRows([{ has_rows: "f" }])).toBe(false); + expect(parseLedgerProbeRows([{}])).toBe(false); + expect(parseLedgerProbeRows([])).toBe(false); + }); +}); diff --git a/ui/hooks/use-migrations.ts b/ui/hooks/use-migrations.ts new file mode 100644 index 00000000..8f55f673 --- /dev/null +++ b/ui/hooks/use-migrations.ts @@ -0,0 +1,298 @@ +import { useQuery } from "@tanstack/react-query"; + +import { useStudio } from "../studio/context"; +import { useIntrospection } from "./use-introspection"; + +const LEDGER_QUERY = ` + select + l."id", l."space", l."migration_name", l."migration_hash", + l."origin_core_hash", l."destination_core_hash", + l."operations", l."created_at", + cb."contract_json" as "contract_json_before", + ca."contract_json" as "contract_json_after" + from "prisma_contract"."ledger" l + left join "prisma_contract"."contract" cb on cb."core_hash" = l."origin_core_hash" + left join "prisma_contract"."contract" ca on ca."core_hash" = l."destination_core_hash" + order by l."id" asc +`; + +/** + * Fallback for databases bootstrapped before the content-addressed + * `prisma_contract.contract` store existed — the ledger alone still + * renders the list; diffs are empty without snapshots. + */ +const LEDGER_QUERY_WITHOUT_CONTRACT = ` + select + "id", "space", "migration_name", "migration_hash", + "origin_core_hash", "destination_core_hash", + "operations", "created_at" + from "prisma_contract"."ledger" + order by "id" asc +`; + +/** + * Cheap navigation-visibility probe: one EXISTS instead of fetching the + * full ledger (whose contract snapshots can be megabytes of jsonb). + */ +const LEDGER_PROBE_QUERY = ` + select exists (select 1 from "prisma_contract"."ledger") as "has_rows" +`; + +export interface StudioMigrationOperationStep { + sql: string; +} + +export interface StudioMigrationOperation { + id: string; + label: string; + operationClass: string; + statements: string[]; +} + +export interface StudioMigration { + id: number; + space: string; + /** Migration directory name; empty for synthesised (db init/update) applies. */ + name: string; + displayName: string; + hash: string; + fromHash: string | null; + toHash: string; + appliedAt: Date | null; + operations: StudioMigrationOperation[]; + contractBefore: unknown; + contractAfter: unknown; + isDestructive: boolean; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function parseJsonish(value: unknown): unknown { + if (typeof value !== "string") { + return value; + } + + try { + return JSON.parse(value); + } catch { + return null; + } +} + +function toDisplayName(migrationName: string): string { + if (migrationName.length === 0) { + return "Schema sync"; + } + + const slug = migrationName.replace(/^\d{8}T\d{4}_/, ""); + + return slug.length > 0 ? slug.replace(/_/g, " ") : migrationName; +} + +function parseOperations(value: unknown): StudioMigrationOperation[] { + const parsed = parseJsonish(value); + + if (!Array.isArray(parsed)) { + return []; + } + + const operations: StudioMigrationOperation[] = []; + + for (const operation of parsed) { + if (!isRecord(operation)) { + continue; + } + + const statements: string[] = []; + + if (Array.isArray(operation.execute)) { + for (const step of operation.execute) { + if (isRecord(step) && typeof step.sql === "string") { + statements.push(step.sql); + } + } + } + + operations.push({ + id: typeof operation.id === "string" ? operation.id : "", + label: typeof operation.label === "string" ? operation.label : "", + operationClass: + typeof operation.operationClass === "string" + ? operation.operationClass + : "additive", + statements, + }); + } + + return operations; +} + +function parseAppliedAt(value: unknown): Date | null { + if (value instanceof Date) { + return value; + } + + if (typeof value === "string") { + const parsed = new Date(value); + + return Number.isNaN(parsed.getTime()) ? null : parsed; + } + + return null; +} + +export function parseLedgerRows( + rows: Record[], +): StudioMigration[] { + const migrations: StudioMigration[] = []; + + for (const row of rows) { + const idValue = row.id; + const id = + typeof idValue === "number" + ? idValue + : typeof idValue === "string" || typeof idValue === "bigint" + ? Number(idValue) + : Number.NaN; + + if (!Number.isFinite(id)) { + continue; + } + + const name = + typeof row.migration_name === "string" ? row.migration_name : ""; + const operations = parseOperations(row.operations); + + migrations.push({ + id, + space: typeof row.space === "string" ? row.space : "app", + name, + displayName: toDisplayName(name), + hash: typeof row.migration_hash === "string" ? row.migration_hash : "", + fromHash: + typeof row.origin_core_hash === "string" && + row.origin_core_hash.length > 0 + ? row.origin_core_hash + : null, + toHash: + typeof row.destination_core_hash === "string" + ? row.destination_core_hash + : "", + appliedAt: parseAppliedAt(row.created_at), + operations, + contractBefore: parseJsonish(row.contract_json_before) ?? null, + contractAfter: parseJsonish(row.contract_json_after) ?? null, + isDestructive: operations.some( + (operation) => operation.operationClass === "destructive", + ), + }); + } + + migrations.sort((left, right) => left.id - right.id); + + return migrations; +} + +/** + * Detects whether the connected database carries a Prisma Next + * migration ledger (`prisma_contract.ledger`) and its hash-keyed + * contract store (`prisma_contract.contract`). Purely derived from + * introspection data — no extra query. + */ +export function useMigrationsDetection(): { + hasPrismaNextMigrations: boolean; + hasContractTable: boolean; +} { + const { data: introspection } = useIntrospection(); + const contractSchema = introspection.schemas["prisma_contract"]; + + return { + hasPrismaNextMigrations: contractSchema?.tables["ledger"] != null, + hasContractTable: contractSchema?.tables["contract"] != null, + }; +} + +export function parseLedgerProbeRows(rows: Record[]): boolean { + const value = rows[0]?.has_rows; + + return value === true || value === "t" || value === "true" || value === 1; +} + +/** + * True when the connected database has a Prisma Next migration ledger + * with at least one row. Drives the Migrations navigation item: a + * database without the `prisma_contract` schema, without the ledger + * table, or with an empty ledger shows no menu entry. Resolves to + * `false` while the probe is in flight, so the item appears only once + * history is confirmed. + */ +export function useHasMigrationHistory(): boolean { + const { adapter } = useStudio(); + const { hasPrismaNextMigrations } = useMigrationsDetection(); + + const query = useQuery({ + enabled: hasPrismaNextMigrations, + queryKey: ["prisma-next-migrations-probe"], + queryFn: async ({ signal }) => { + const [error, result] = await adapter.raw( + { sql: LEDGER_PROBE_QUERY }, + { abortSignal: signal }, + ); + + if (error) { + throw error; + } + + return parseLedgerProbeRows(result.rows); + }, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + retry: false, + staleTime: 30_000, + }); + + return hasPrismaNextMigrations && query.data === true; +} + +/** + * Loads the Prisma Next migration history from + * `prisma_contract.ledger`, newest first. + */ +export function useMigrations() { + const { adapter } = useStudio(); + const { hasPrismaNextMigrations, hasContractTable } = + useMigrationsDetection(); + + const query = useQuery({ + enabled: hasPrismaNextMigrations, + queryKey: ["prisma-next-migrations", "contract-table", hasContractTable], + queryFn: async ({ signal }) => { + const [error, result] = await adapter.raw( + { + sql: hasContractTable ? LEDGER_QUERY : LEDGER_QUERY_WITHOUT_CONTRACT, + }, + { abortSignal: signal }, + ); + + if (error) { + throw error; + } + + return parseLedgerRows(result.rows).reverse(); + }, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + retry: false, + staleTime: 30_000, + }); + + const migrations: StudioMigration[] = query.data ?? []; + + return { + ...query, + hasPrismaNextMigrations, + migrations, + }; +} diff --git a/ui/hooks/use-navigation.tsx b/ui/hooks/use-navigation.tsx index 371d816c..5b26cdd1 100644 --- a/ui/hooks/use-navigation.tsx +++ b/ui/hooks/use-navigation.tsx @@ -170,6 +170,7 @@ function useNavigationInternal() { const [filterParam, setFilterParam] = useQueryState("filter", { defaultValue: defaults.filter, }); + const [migrationParam, setMigrationParam] = useQueryState("migration"); const [pageIndexParam, setPageIndexParam] = useQueryState("pageIndex", { defaultValue: defaults.pageIndex, }); @@ -243,6 +244,7 @@ function useNavigationInternal() { metadata, createUrl, filterParam, + migrationParam, pageIndexParam, pageSizeParam, pinParam, @@ -259,6 +261,7 @@ function useNavigationInternal() { tableParam, viewParam: resolvedViewParam, setFilterParam: setFilterParam as NuqsSetNullableValue, + setMigrationParam: setMigrationParam as NuqsSetNullableValue, setPageIndexParam: setPageIndexParam as NuqsSetNullableValue, setPageSizeParam: setPageSizeParam as NuqsSetNullableValue, setPinParam: setPinParam as NuqsSetNullableValue, diff --git a/ui/index.css b/ui/index.css index ef53bc8f..f0114c7e 100644 --- a/ui/index.css +++ b/ui/index.css @@ -273,3 +273,26 @@ [data-radix-popper-content-wrapper] { z-index: 950 !important; } + +/* Migrations view: morph shared diff nodes between selections instead of + tearing the canvas down. Node ids are stable (`model:`), so a + transform transition glides each surviving card to its new layout + position while the camera fitView animates alongside. */ +.migrations-diff-canvas .react-flow__node { + transition: transform 500ms cubic-bezier(0.33, 1, 0.68, 1); + animation: migrations-node-enter 300ms ease-out; +} + +.migrations-diff-canvas .react-flow__node.dragging { + transition: none; +} + +.migrations-diff-canvas .react-flow__edge { + animation: migrations-node-enter 400ms ease-out; +} + +@keyframes migrations-node-enter { + from { + opacity: 0; + } +} diff --git a/ui/studio/CommandPalette.test.tsx b/ui/studio/CommandPalette.test.tsx index f3729e2d..3e0c92af 100644 --- a/ui/studio/CommandPalette.test.tsx +++ b/ui/studio/CommandPalette.test.tsx @@ -54,6 +54,10 @@ vi.mock("../hooks/use-navigation", () => ({ useNavigation: () => useNavigationMock(), })); +vi.mock("../hooks/use-migrations", () => ({ + useHasMigrationHistory: () => false, +})); + vi.mock("../hooks/use-introspection", () => ({ useIntrospection: () => useIntrospectionMock(), })); diff --git a/ui/studio/Navigation.test.tsx b/ui/studio/Navigation.test.tsx index 373c86e9..1ba6a974 100644 --- a/ui/studio/Navigation.test.tsx +++ b/ui/studio/Navigation.test.tsx @@ -64,6 +64,7 @@ interface StudioMockValue { const useNavigationMock = vi.fn<() => NavigationMockValue>(); const useIntrospectionMock = vi.fn<() => IntrospectionMockValue>(); const useStreamsMock = vi.fn<() => StreamsMockValue>(); +const useHasMigrationHistoryMock = vi.fn<() => boolean>(() => false); const useStudioMock = vi.fn<() => StudioMockValue>(); const uiStateValues = new Map(); const setNavigationWidthMock = vi.fn<(width: number) => void>(); @@ -78,6 +79,10 @@ vi.mock("../hooks/use-introspection", () => ({ useIntrospection: () => useIntrospectionMock(), })); +vi.mock("../hooks/use-migrations", () => ({ + useHasMigrationHistory: () => useHasMigrationHistoryMock(), +})); + vi.mock("../hooks/use-streams", () => ({ useStreams: () => useStreamsMock(), })); @@ -260,6 +265,7 @@ function getSearchBlock( describe("Navigation", () => { beforeEach(() => { isDarkMode = false; + useHasMigrationHistoryMock.mockReturnValue(false); setNavigationWidthMock.mockReset(); refetchIntrospectionMock.mockReset(); refetchStreamsMock.mockReset(); @@ -552,6 +558,50 @@ describe("Navigation", () => { container.remove(); }); + it("shows Migrations only when the ledger holds applied migrations", () => { + // useHasMigrationHistory resolves false for a missing prisma_contract + // schema, a missing ledger table, or an empty ledger — all three hide + // the item (mock default from beforeEach). + const withoutHistoryContainer = document.createElement("div"); + document.body.appendChild(withoutHistoryContainer); + const withoutHistoryRoot = createRoot(withoutHistoryContainer); + + act(() => { + withoutHistoryRoot.render(); + }); + + expect(withoutHistoryContainer.textContent).not.toContain("Migrations"); + + act(() => { + withoutHistoryRoot.unmount(); + }); + withoutHistoryContainer.remove(); + + useHasMigrationHistoryMock.mockReturnValue(true); + + const container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + + act(() => { + root.render(); + }); + + const migrationsLink = container.querySelector( + '[data-testid="navigation-migrations-item"]', + ); + + expect(migrationsLink).not.toBeNull(); + expect(migrationsLink?.getAttribute("href")).toBe( + "#schemaParam=public&viewParam=migrations", + ); + + act(() => { + root.unmount(); + }); + container.remove(); + }); + it("preserves selected schema when navigating between Studio views", () => { useStudioMock.mockImplementation(() => ({ hasDatabase: true, diff --git a/ui/studio/Navigation.tsx b/ui/studio/Navigation.tsx index 900a637e..ac175c73 100644 --- a/ui/studio/Navigation.tsx +++ b/ui/studio/Navigation.tsx @@ -14,6 +14,7 @@ import { } from "../components/ui/select"; import { Skeleton } from "../components/ui/skeleton"; import { useIntrospection } from "../hooks/use-introspection"; +import { useHasMigrationHistory } from "../hooks/use-migrations"; import { useNavigation } from "../hooks/use-navigation"; import { useNavigationTableList } from "../hooks/use-navigation-table-list"; import { useStreams } from "../hooks/use-streams"; @@ -51,6 +52,7 @@ export function Navigation({ className }: NavigationProps) { const { isFetching, activeTable } = metadata; const { errorState, hasResolvedIntrospection, isRefetching, refetch } = useIntrospection(); + const hasMigrationHistory = useHasMigrationHistory(); const [tableSearchUiState, setTableSearchUiState] = useUiState(TABLE_SEARCH_UI_STATE_KEY, { isOpen: false, @@ -575,6 +577,24 @@ export function Navigation({ className }: NavigationProps) { SQL + {hasMigrationHistory && ( + + + Migrations + + + )} JSX.Element | null> = { stream: StreamView, console: ConsoleView, sql: SqlView, + migrations: MigrationsView, default: BasicView, }; diff --git a/ui/studio/views/migrations/MigrationsView.test.tsx b/ui/studio/views/migrations/MigrationsView.test.tsx new file mode 100644 index 00000000..5f577f9b --- /dev/null +++ b/ui/studio/views/migrations/MigrationsView.test.tsx @@ -0,0 +1,440 @@ +import type { ReactNode } from "react"; +import { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import type { StudioMigration } from "../../../hooks/use-migrations"; +import { MigrationsView } from "./MigrationsView"; + +const { useMigrationsMock, useNavigationMock, setMigrationParamMock } = + vi.hoisted(() => ({ + useMigrationsMock: vi.fn(), + useNavigationMock: vi.fn(), + setMigrationParamMock: vi.fn(() => Promise.resolve(new URLSearchParams())), + })); + +vi.mock("../../../hooks/use-migrations", () => ({ + useMigrations: useMigrationsMock, +})); + +vi.mock("../../../hooks/use-navigation", () => ({ + useNavigation: useNavigationMock, +})); + +vi.mock("../../StudioHeader", () => ({ + StudioHeader: ({ children }: { children?: ReactNode }) => ( +
{children}
+ ), +})); + +vi.mock("reactflow", () => ({ + __esModule: true, + default: ({ children }: { children?: ReactNode }) => ( +
{children}
+ ), + Background: () => null, + Controls: () => null, + Handle: () => null, + Position: { Left: "left", Right: "right", Top: "top", Bottom: "bottom" }, +})); + +vi.mock("./diff-layout", async () => { + const actual = + await vi.importActual("./diff-layout"); + + return { + ...actual, + layoutMigrationDiffNodes: (nodes: unknown[]) => Promise.resolve(nodes), + }; +}); + +( + globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean } +).IS_REACT_ACT_ENVIRONMENT = true; + +function contract(models: Record>): unknown { + const domainModels: Record = {}; + + for (const [name, fields] of Object.entries(models)) { + domainModels[name] = { + fields: Object.fromEntries( + Object.entries(fields).map(([fieldName]) => [ + fieldName, + { nullable: false, type: { kind: "scalar", codecId: "pg/text@1" } }, + ]), + ), + relations: {}, + storage: { + fields: Object.fromEntries( + Object.entries(fields).map(([fieldName]) => [ + fieldName, + { column: fieldName }, + ]), + ), + namespaceId: "public", + table: name.toLowerCase(), + }, + }; + } + + return { + domain: { namespaces: { public: { models: domainModels } } }, + storage: { namespaces: {} }, + }; +} + +function migration(overrides: Partial): StudioMigration { + return { + id: 1, + space: "app", + name: "20260702T2236_init_users", + displayName: "init users", + hash: "sha256:mig1", + fromHash: null, + toHash: "sha256:c1", + appliedAt: new Date("2026-07-02T22:36:00Z"), + operations: [ + { + id: "op.create", + label: 'Create table "user"', + operationClass: "additive", + statements: ['CREATE TABLE "user" ()'], + }, + ], + contractBefore: null, + contractAfter: contract({ User: { id: {}, email: {} } }), + isDestructive: false, + ...overrides, + }; +} + +function renderView() { + const container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + + act(() => { + root.render(); + }); + + return { + container, + cleanup: () => { + act(() => { + root.unmount(); + }); + container.remove(); + }, + }; +} + +describe("MigrationsView", () => { + beforeEach(() => { + useNavigationMock.mockReturnValue({ + migrationParam: null, + setMigrationParam: setMigrationParamMock, + }); + useMigrationsMock.mockReturnValue({ + hasPrismaNextMigrations: true, + isLoading: false, + isError: false, + migrations: [ + migration({ + id: 2, + name: "20260702T2237_add_projects", + displayName: "add projects", + fromHash: "sha256:c1", + toHash: "sha256:c2", + contractBefore: contract({ User: { id: {}, email: {} } }), + contractAfter: contract({ + User: { id: {}, email: {} }, + Project: { id: {}, name: {} }, + }), + }), + migration({ id: 1 }), + ], + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + document.body.innerHTML = ""; + }); + + it("lists every migration newest first with the latest selected", () => { + const { container, cleanup } = renderView(); + + const items = Array.from( + container.querySelectorAll('[data-testid^="migration-list-item-"]'), + ); + + expect(items).toHaveLength(2); + expect(items[0]?.getAttribute("data-testid")).toBe("migration-list-item-2"); + expect( + container.querySelector('[data-testid="migration-title"]')?.textContent, + ).toBe("add projects"); + + cleanup(); + }); + + it("selects a migration through the URL state", () => { + const { container, cleanup } = renderView(); + + const olderItem = container.querySelector( + '[data-testid="migration-list-item-1"]', + ); + + act(() => { + olderItem?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + expect(setMigrationParamMock).toHaveBeenCalledWith("1"); + + cleanup(); + }); + + it("renders the diff for the migration selected via URL state", () => { + useNavigationMock.mockReturnValue({ + migrationParam: "1", + setMigrationParam: setMigrationParamMock, + }); + + const { container, cleanup } = renderView(); + + expect( + container.querySelector('[data-testid="migration-title"]')?.textContent, + ).toBe("init users"); + + cleanup(); + }); + + it("toggles the SQL panel with per-operation statements", () => { + const { container, cleanup } = renderView(); + + expect( + container.querySelector('[data-testid="migration-sql-panel"]'), + ).toBeNull(); + + const sqlButton = Array.from(container.querySelectorAll("button")).find( + (button) => button.textContent?.includes("SQL"), + ); + + act(() => { + sqlButton?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + const panel = container.querySelector( + '[data-testid="migration-sql-panel"]', + ); + + expect(panel).not.toBeNull(); + expect(panel?.textContent).toContain('CREATE TABLE "user" ()'); + + cleanup(); + }); + + it("toggles the Schema panel with a rendered schema diff", () => { + const { container, cleanup } = renderView(); + + const schemaButton = container.querySelector( + '[data-testid="migration-panel-schema"]', + ); + + act(() => { + schemaButton?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + const panel = container.querySelector( + '[data-testid="migration-schema-panel"]', + ); + + expect(panel).not.toBeNull(); + expect(panel?.textContent).toContain("model Project {"); + + cleanup(); + }); + + it("expands a collapsed unchanged run in the schema diff on click", () => { + const wideUser = Object.fromEntries( + Array.from({ length: 10 }, (_, index) => [`field${index}`, {}]), + ); + + useMigrationsMock.mockReturnValue({ + hasPrismaNextMigrations: true, + isLoading: false, + isError: false, + migrations: [ + migration({ + id: 2, + fromHash: "sha256:c1", + toHash: "sha256:c2", + contractBefore: contract({ User: wideUser }), + contractAfter: contract({ + User: wideUser, + Project: { id: {}, name: {} }, + }), + }), + ], + }); + + const { container, cleanup } = renderView(); + + act(() => { + container + .querySelector('[data-testid="migration-panel-schema"]') + ?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + const panel = container.querySelector( + '[data-testid="migration-schema-panel"]', + ); + const fold = container.querySelector('[data-testid="schema-diff-expand"]'); + + expect(fold?.textContent).toContain("unchanged line"); + expect(fold?.textContent).toContain("expand"); + // The folded run hides the User model's trailing fields. + expect(panel?.textContent).not.toContain("field5 String"); + + act(() => { + fold?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + expect( + container.querySelector('[data-testid="schema-diff-expand"]'), + ).toBeNull(); + expect(panel?.textContent).toContain("field5 String"); + + cleanup(); + }); + + it("shows an upgrade notice instead of the canvas when no row carries a contract", () => { + useMigrationsMock.mockReturnValue({ + hasPrismaNextMigrations: true, + isLoading: false, + isError: false, + migrations: [ + migration({ id: 2, contractBefore: null, contractAfter: null }), + migration({ id: 1, contractBefore: null, contractAfter: null }), + ], + }); + + const { container, cleanup } = renderView(); + + const notice = container.querySelector( + '[data-testid="migration-contract-upgrade-notice"]', + ); + + expect(notice?.textContent).toContain( + "update to the latest version of Prisma Next", + ); + expect(container.querySelector('[data-testid="diff-canvas"]')).toBeNull(); + // Diff-dependent controls hide; the SQL panel still works off ledger data. + expect( + container.querySelector('[data-testid="migration-show-all-models"]'), + ).toBeNull(); + expect( + container.querySelector('[data-testid="migration-panel-schema"]'), + ).toBeNull(); + expect( + container.querySelector('[data-testid="migration-panel-sql"]'), + ).not.toBeNull(); + + cleanup(); + }); + + it("renders an all-models toggle for the diff canvas", () => { + const { container, cleanup } = renderView(); + + expect( + container.querySelector('[data-testid="migration-show-all-models"]'), + ).not.toBeNull(); + + cleanup(); + }); + + it("resizes the details panel from its drag handle via keyboard", () => { + const { container, cleanup } = renderView(); + + const sqlButton = container.querySelector( + '[data-testid="migration-panel-sql"]', + ); + + act(() => { + sqlButton?.dispatchEvent( + new MouseEvent("click", { bubbles: true, cancelable: true }), + ); + }); + + const panel = container.querySelector( + '[data-testid="migration-details-panel"]', + ); + const handle = container.querySelector( + '[data-testid="migration-panel-resize-handle"]', + ); + + expect(panel).not.toBeNull(); + expect(handle).not.toBeNull(); + expect(panel?.style.height).toBe("256px"); + + act(() => { + handle?.dispatchEvent( + new KeyboardEvent("keydown", { + bubbles: true, + cancelable: true, + key: "ArrowUp", + }), + ); + }); + + expect( + container.querySelector( + '[data-testid="migration-details-panel"]', + )?.style.height, + ).toBe("272px"); + + act(() => { + handle?.dispatchEvent( + new KeyboardEvent("keydown", { + bubbles: true, + cancelable: true, + key: "ArrowDown", + }), + ); + }); + + expect( + container.querySelector( + '[data-testid="migration-details-panel"]', + )?.style.height, + ).toBe("256px"); + + cleanup(); + }); + + it("shows an empty state when no ledger is detected", () => { + useMigrationsMock.mockReturnValue({ + hasPrismaNextMigrations: false, + isLoading: false, + isError: false, + migrations: [], + }); + + const { container, cleanup } = renderView(); + + expect(container.textContent).toContain( + "No Prisma Next migration ledger detected", + ); + + cleanup(); + }); +}); diff --git a/ui/studio/views/migrations/MigrationsView.tsx b/ui/studio/views/migrations/MigrationsView.tsx new file mode 100644 index 00000000..1044f605 --- /dev/null +++ b/ui/studio/views/migrations/MigrationsView.tsx @@ -0,0 +1,1048 @@ +import dayjs from "dayjs"; +import { + ArrowRight, + FileDiff, + GitBranch, + Key, + Terminal, + TriangleAlert, +} from "lucide-react"; +import { type FC, memo, useEffect, useMemo, useRef, useState } from "react"; +import ReactFlow, { + Background, + Controls, + type Edge, + Handle, + type NodeProps, + type NodeTypes, + Position, + type ReactFlowInstance, +} from "reactflow"; + +import { Badge } from "../../../components/ui/badge"; +import { Button } from "../../../components/ui/button"; +import { Skeleton } from "../../../components/ui/skeleton"; +import { Switch } from "../../../components/ui/switch"; +import { + type StudioMigration, + useMigrations, +} from "../../../hooks/use-migrations"; +import { useNavigation } from "../../../hooks/use-navigation"; +import { useUiState } from "../../../hooks/use-ui-state"; +import { cn } from "../../../lib/utils"; +import { StudioHeader } from "../../StudioHeader"; +import type { ViewProps } from "../View"; +import { + diffContracts, + type DiffStatus, + type FieldDiff, + parseContractSnapshot, + summarizeDiff, +} from "./contract-diff"; +import { + buildDiffGraph, + type EnumDiffNodeData, + layoutMigrationDiffNodes, + type MigrationDiffNode, + type ModelDiffNodeData, +} from "./diff-layout"; +import { + diffSchemas, + renderPslSchema, + schemaDiffHasChanges, + type SchemaDiffLine, +} from "./psl-schema"; + +const STATUS_STYLES: Record< + DiffStatus, + { + card: string; + header: string; + badge: string; + badgeLabel: string; + tape: string; + } +> = { + added: { + card: "border-emerald-400/80 bg-emerald-50 dark:border-emerald-600/70 dark:bg-emerald-950/60", + header: "text-emerald-900 dark:text-emerald-100", + badge: + "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 border-emerald-500/30", + badgeLabel: "new", + tape: "bg-emerald-300/70 dark:bg-emerald-700/70", + }, + removed: { + card: "border-rose-400/80 bg-rose-50 dark:border-rose-600/70 dark:bg-rose-950/60", + header: "text-rose-900 line-through decoration-2 dark:text-rose-100", + badge: "bg-rose-500/15 text-rose-700 dark:text-rose-300 border-rose-500/30", + badgeLabel: "removed", + tape: "bg-rose-300/70 dark:bg-rose-700/70", + }, + changed: { + card: "border-amber-400/80 bg-amber-50 dark:border-amber-600/70 dark:bg-amber-950/50", + header: "text-amber-900 dark:text-amber-100", + badge: + "bg-amber-500/15 text-amber-700 dark:text-amber-300 border-amber-500/30", + badgeLabel: "updated", + tape: "bg-amber-300/70 dark:bg-amber-700/70", + }, + unchanged: { + card: "border-border bg-card opacity-70", + header: "text-foreground", + badge: "bg-muted text-muted-foreground border-border", + badgeLabel: "unchanged", + tape: "bg-muted-foreground/20", + }, +}; + +const FIELD_STATUS_GLYPHS: Record< + DiffStatus, + { glyph: string; className: string } +> = { + added: { + glyph: "+", + className: + "bg-emerald-500/20 text-emerald-700 dark:text-emerald-300 font-bold", + }, + removed: { + glyph: "−", + className: "bg-rose-500/20 text-rose-700 dark:text-rose-300 font-bold", + }, + changed: { + glyph: "~", + className: "bg-amber-500/20 text-amber-700 dark:text-amber-300 font-bold", + }, + unchanged: { + glyph: "·", + className: "text-muted-foreground/60", + }, +}; + +const DETAILS_PANEL_DEFAULT_HEIGHT = 256; +const DETAILS_PANEL_MIN_HEIGHT = 120; +const DETAILS_PANEL_MAX_HEIGHT = 640; + +function clampDetailsPanelHeight(height: number): number { + return Math.min( + DETAILS_PANEL_MAX_HEIGHT, + Math.max(DETAILS_PANEL_MIN_HEIGHT, Math.round(height)), + ); +} + +/** Deterministic sticky-note tilt so the canvas feels hand-placed. */ +function cardRotation(seed: string): number { + let hash = 0; + + for (let index = 0; index < seed.length; index += 1) { + hash = (hash * 31 + seed.charCodeAt(index)) | 0; + } + + const tilts = [-1.4, -0.7, 0, 0.7, 1.4]; + + return tilts[Math.abs(hash) % tilts.length] ?? 0; +} + +function shortHash(hash: string | null): string { + if (!hash) { + return "∅"; + } + + return hash.replace(/^sha256:/, "").slice(0, 7); +} + +const FieldRow: FC<{ field: FieldDiff }> = ({ field }) => { + const glyph = FIELD_STATUS_GLYPHS[field.status]; + + return ( +
+
+ + {glyph.glyph} + + {field.field.isPrimaryKey && ( + + )} + + {field.name} + + + {field.field.type} + {field.field.nullable ? "?" : ""} + +
+ {field.details.map((detail) => ( +
+ + {detail.before} + + + + {detail.after} + +
+ ))} +
+ ); +}; + +const ModelDiffNodeComponent: FC> = memo( + ({ data }) => { + const { model } = data; + const styles = STATUS_STYLES[model.status]; + const rotation = cardRotation(model.name); + const structureChips = [ + ...model.addedIndexes.map((index) => ({ + key: `+${index}`, + label: `+ ${index}`, + className: + "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 border-emerald-500/30", + })), + ...model.removedIndexes.map((index) => ({ + key: `-${index}`, + label: `− ${index}`, + className: + "bg-rose-500/15 text-rose-700 dark:text-rose-300 border-rose-500/30 line-through", + })), + ]; + + return ( +
+ +
+
+
+
+ {model.name} +
+ {model.table && model.table !== model.name && ( +
+ {model.table} +
+ )} +
+ + {styles.badgeLabel} + +
+
+ {model.fields.map((field) => ( + + ))} +
+ {structureChips.length > 0 && ( +
+ {structureChips.map((chip) => ( + + {chip.label} + + ))} +
+ )} + +
+ ); + }, +); + +ModelDiffNodeComponent.displayName = "ModelDiffNodeComponent"; + +const EnumDiffNodeComponent: FC> = memo( + ({ data }) => { + const { enumDiff } = data; + const rotation = cardRotation(enumDiff.name); + const cardStatus = + enumDiff.status === "unchanged" ? "unchanged" : enumDiff.status; + + return ( +
+ +
+
+ + {enumDiff.name} + + + enum + +
+
+ {enumDiff.members.map((member) => { + const glyph = FIELD_STATUS_GLYPHS[member.status]; + + return ( +
+ + {glyph.glyph} + + {member.name} +
+ ); + })} +
+ +
+ ); + }, +); + +EnumDiffNodeComponent.displayName = "EnumDiffNodeComponent"; + +const nodeTypes: NodeTypes = { + modelDiff: ModelDiffNodeComponent, + enumDiff: EnumDiffNodeComponent, +}; + +// Memoized: the details-panel drag handler updates MigrationsView state on +// every pointermove; stable props keep the ReactFlow subtree out of those +// re-renders. +const MigrationDiffCanvas = memo(function MigrationDiffCanvas(props: { + migration: StudioMigration; + showAllModels: boolean; +}) { + const { migration, showAllModels } = props; + const diff = useMemo( + () => diffContracts(migration.contractBefore, migration.contractAfter), + [migration.contractBefore, migration.contractAfter], + ); + const graph = useMemo( + () => buildDiffGraph(diff, showAllModels), + [diff, showAllModels], + ); + const [layoutedGraph, setLayoutedGraph] = useState<{ + nodes: MigrationDiffNode[]; + edges: Edge[]; + }>({ nodes: [], edges: [] }); + const reactFlowInstanceRef = useRef(null); + + useEffect(() => { + let cancelled = false; + + void layoutMigrationDiffNodes(graph.nodes, graph.edges).then((nodes) => { + if (cancelled) { + return; + } + + // Nodes and edges swap together so the morph transition animates + // shared nodes (stable `model:` ids) to their new positions + // instead of tearing the whole canvas down. + setLayoutedGraph({ nodes, edges: graph.edges }); + + if (typeof window !== "undefined") { + window.requestAnimationFrame(() => { + window.requestAnimationFrame(() => { + void reactFlowInstanceRef.current?.fitView({ + duration: 500, + padding: 0.18, + }); + }); + }); + } + }); + + return () => { + cancelled = true; + }; + }, [graph]); + + if (migration.contractAfter == null && migration.contractBefore == null) { + return ( +
+ This migration was applied before contract snapshots were recorded, so + there is no visual diff to show. +
+ ); + } + + return ( + { + reactFlowInstanceRef.current = instance; + }} + proOptions={{ hideAttribution: true }} + > + + + + ); +}); + +function MigrationListItem(props: { + index: number; + isSelected: boolean; + migration: StudioMigration; + onSelect: () => void; +}) { + const { index, isSelected, migration, onSelect } = props; + const stats = useMemo( + () => + summarizeDiff( + diffContracts(migration.contractBefore, migration.contractAfter).stats, + ), + [migration.contractBefore, migration.contractAfter], + ); + + return ( + + ); +} + +function MigrationSqlPanel(props: { migration: StudioMigration }) { + const { migration } = props; + + return ( +
+
+ {migration.operations.map((operation, index) => ( +
+
+ + {operation.operationClass} + + + {operation.label} + +
+ {operation.statements.map((statement, index) => ( +
+                {statement}
+              
+ ))} +
+ ))} +
+
+ ); +} + +const SCHEMA_DIFF_LINE_STYLES: Record< + SchemaDiffLine["kind"], + { row: string; gutter: string; symbol: string } +> = { + added: { + row: "bg-emerald-500/10 text-emerald-800 dark:text-emerald-200", + gutter: "text-emerald-600 dark:text-emerald-400", + symbol: "+", + }, + removed: { + row: "bg-rose-500/10 text-rose-800 dark:text-rose-200", + gutter: "text-rose-600 dark:text-rose-400", + symbol: "−", + }, + context: { + row: "text-muted-foreground", + gutter: "text-transparent", + symbol: " ", + }, + collapsed: { + row: "text-muted-foreground/60 italic", + gutter: "text-transparent", + symbol: " ", + }, +}; + +function SchemaDiffRow(props: { line: SchemaDiffLine }) { + const { line } = props; + + return ( +
+ + {SCHEMA_DIFF_LINE_STYLES[line.kind].symbol} + + {line.text} +
+ ); +} + +function MigrationSchemaPanel(props: { migration: StudioMigration }) { + const { migration } = props; + const lines = useMemo( + () => + diffSchemas( + renderPslSchema(parseContractSnapshot(migration.contractBefore)), + renderPslSchema(parseContractSnapshot(migration.contractAfter)), + ), + [migration.contractBefore, migration.contractAfter], + ); + const [expandedFolds, setExpandedFolds] = useState>( + () => new Set(), + ); + + return ( +
+ {schemaDiffHasChanges(lines) ? ( +
+ {lines.map((line, index) => { + if (line.kind !== "collapsed") { + return ; + } + + if (expandedFolds.has(index)) { + return (line.hiddenLines ?? []).map((text, hiddenIndex) => ( + + )); + } + + return ( + + ); + })} +
+ ) : ( +
+ No schema-level changes in this migration. +
+ )} +
+ ); +} + +type MigrationDetailsPanelMode = "sql" | "schema" | null; + +export function MigrationsView(_props: ViewProps) { + const { hasPrismaNextMigrations, isLoading, isError, migrations } = + useMigrations(); + const { migrationParam, setMigrationParam } = useNavigation(); + const [detailsPanel, setDetailsPanel] = + useState(null); + const [showAllModels, setShowAllModels] = useUiState( + "migrations:show-all-models", + false, + ); + const [detailsPanelHeight, setDetailsPanelHeight] = useUiState( + "migrations:details-panel-height", + DETAILS_PANEL_DEFAULT_HEIGHT, + ); + const [draftPanelHeight, setDraftPanelHeight] = useState(null); + const [isPanelResizing, setIsPanelResizing] = useState(false); + const panelResizeStateRef = useRef<{ + startHeight: number; + startY: number; + } | null>(null); + const resolvedPanelHeight = clampDetailsPanelHeight( + draftPanelHeight ?? detailsPanelHeight, + ); + + useEffect(() => { + if (!isPanelResizing) { + return; + } + + const previousCursor = document.body.style.cursor; + const previousUserSelect = document.body.style.userSelect; + document.body.style.cursor = "row-resize"; + document.body.style.userSelect = "none"; + + const handlePointerMove = (event: PointerEvent) => { + const resizeState = panelResizeStateRef.current; + + if (!resizeState) { + return; + } + + setDraftPanelHeight( + clampDetailsPanelHeight( + resizeState.startHeight + (resizeState.startY - event.clientY), + ), + ); + }; + + const handlePointerUp = (event: PointerEvent) => { + const resizeState = panelResizeStateRef.current; + + if (!resizeState) { + return; + } + + const nextHeight = clampDetailsPanelHeight( + resizeState.startHeight + (resizeState.startY - event.clientY), + ); + + panelResizeStateRef.current = null; + setDraftPanelHeight(null); + setIsPanelResizing(false); + setDetailsPanelHeight(nextHeight); + }; + + window.addEventListener("pointermove", handlePointerMove); + window.addEventListener("pointerup", handlePointerUp); + window.addEventListener("pointercancel", handlePointerUp); + + return () => { + document.body.style.cursor = previousCursor; + document.body.style.userSelect = previousUserSelect; + window.removeEventListener("pointermove", handlePointerMove); + window.removeEventListener("pointerup", handlePointerUp); + window.removeEventListener("pointercancel", handlePointerUp); + }; + }, [isPanelResizing, setDetailsPanelHeight]); + + const selectedMigration = useMemo(() => { + if (migrationParam) { + const match = migrations.find( + (migration) => String(migration.id) === migrationParam, + ); + + if (match) { + return match; + } + } + + return migrations[0] ?? null; + }, [migrationParam, migrations]); + + const selectedStats = useMemo( + () => + selectedMigration + ? summarizeDiff( + diffContracts( + selectedMigration.contractBefore, + selectedMigration.contractAfter, + ).stats, + ) + : [], + [selectedMigration], + ); + + // Ledger rows without a single contract snapshot mean the database was + // written by a prisma-next predating the 1:1 contract table (or the + // table was never populated) — there is nothing to diff, so the canvas + // yields to an upgrade notice. Any one non-null snapshot renders + // normally with whatever data exists. + const contractDataMissing = + migrations.length > 0 && + migrations.every((migration) => migration.contractAfter == null); + + return ( +
+ +
+ + Migrations + {migrations.length > 0 && ( + {migrations.length} + )} +
+
+ + {!hasPrismaNextMigrations ? ( +
+ No Prisma Next migration ledger detected in this database. +
+ ) : isLoading ? ( +
+
+ {Array.from({ length: 8 }).map((_, index) => ( + + ))} +
+ +
+ ) : isError ? ( +
+ Failed to load the migration ledger. Check the database connection and + retry. +
+ ) : migrations.length === 0 ? ( +
+ The migration ledger is empty — apply a migration with prisma-next to + see it here. +
+ ) : ( +
+ + +
+ {selectedMigration && ( + <> +
+

+ {selectedMigration.displayName} +

+
+ {shortHash(selectedMigration.fromHash)} + + {shortHash(selectedMigration.toHash)} + {selectedMigration.appliedAt && ( + + applied{" "} + {dayjs(selectedMigration.appliedAt).format( + "MMM D, YYYY HH:mm:ss", + )} + + )} +
+
+ {selectedStats.map((chip) => ( + + {chip} + + ))} +
+
+ {!contractDataMissing && ( +
+ + setShowAllModels(checked === true) + } + /> + +
+ )} +
+ + {!contractDataMissing && ( + + )} +
+
+
+ +
+ {contractDataMissing ? ( +
+ Please update to the latest version of Prisma Next to view + migrations in Studio +
+ ) : ( +
+ +
+ )} +
+ + {detailsPanel !== null && ( +
+ +
+ {detailsPanel === "sql" ? ( + + ) : ( + + )} +
+
+ )} + + )} +
+
+ )} +
+ ); +} diff --git a/ui/studio/views/migrations/contract-diff.test.ts b/ui/studio/views/migrations/contract-diff.test.ts new file mode 100644 index 00000000..1234a26b --- /dev/null +++ b/ui/studio/views/migrations/contract-diff.test.ts @@ -0,0 +1,423 @@ +import { describe, expect, it } from "vitest"; + +import { + diffContracts, + parseContractSnapshot, + summarizeDiff, +} from "./contract-diff"; + +interface FieldSpec { + codec?: string; + nativeType?: string; + nullable?: boolean; + defaultValue?: unknown; + enumName?: string; +} + +interface ModelSpec { + table?: string; + primaryKey?: string[]; + fields: Record; + relations?: Record; + indexes?: string[][]; + uniques?: string[][]; +} + +interface ContractSpec { + models: Record; + enums?: Record; +} + +function makeContract(spec: ContractSpec): unknown { + const models: Record = {}; + const tables: Record = {}; + + for (const [modelName, model] of Object.entries(spec.models)) { + const table = model.table ?? modelName.toLowerCase(); + const fields: Record = {}; + const storageFields: Record = {}; + const columns: Record = {}; + + for (const [fieldName, field] of Object.entries(model.fields)) { + fields[fieldName] = { + nullable: field.nullable ?? false, + type: { kind: "scalar", codecId: field.codec ?? "pg/text@1" }, + ...(field.enumName + ? { + valueSet: { + entityKind: "enum", + entityName: field.enumName, + namespaceId: "public", + plane: "domain", + }, + } + : {}), + }; + storageFields[fieldName] = { column: fieldName }; + columns[fieldName] = { + codecId: field.codec ?? "pg/text@1", + nativeType: field.nativeType ?? "text", + nullable: field.nullable ?? false, + ...(field.defaultValue !== undefined + ? { + default: + typeof field.defaultValue === "string" && + field.defaultValue.endsWith("()") + ? { kind: "function", expression: field.defaultValue } + : { kind: "literal", value: field.defaultValue }, + } + : {}), + }; + } + + const relations: Record = {}; + + for (const [relationName, relation] of Object.entries( + model.relations ?? {}, + )) { + relations[relationName] = { + cardinality: relation.cardinality ?? "N:1", + to: { model: relation.toModel, namespace: "public" }, + on: { localFields: ["id"], targetFields: ["id"] }, + }; + } + + models[modelName] = { + fields, + relations, + storage: { fields: storageFields, namespaceId: "public", table }, + }; + tables[table] = { + columns, + primaryKey: { columns: model.primaryKey ?? ["id"] }, + indexes: (model.indexes ?? []).map((columnsList) => ({ + columns: columnsList, + })), + uniques: (model.uniques ?? []).map((columnsList) => ({ + columns: columnsList, + })), + foreignKeys: [], + }; + } + + const enums: Record = {}; + + for (const [enumName, members] of Object.entries(spec.enums ?? {})) { + enums[enumName] = { + codecId: "pg/text@1", + members: members.map((member) => ({ name: member, value: member })), + }; + } + + return { + schemaVersion: "1", + targetFamily: "sql", + target: "postgres", + domain: { namespaces: { public: { models, enum: enums } } }, + storage: { + namespaces: { public: { entries: { table: tables }, id: "public" } }, + }, + }; +} + +const baseUser: ModelSpec = { + table: "user", + fields: { + id: { codec: "pg/uuid@1", nativeType: "uuid" }, + email: {}, + name: {}, + }, +}; + +describe("parseContractSnapshot", () => { + it("normalizes models, fields, and storage details", () => { + const snapshot = parseContractSnapshot( + makeContract({ + models: { + User: { + ...baseUser, + fields: { + ...baseUser.fields, + createdAt: { + codec: "pg/timestamptz@1", + nativeType: "timestamptz", + defaultValue: "now()", + }, + }, + }, + }, + }), + ); + + const user = snapshot.models.get("User"); + expect(user).toBeDefined(); + expect(user?.table).toBe("user"); + expect(user?.fields.map((field) => field.name)).toEqual([ + "id", + "createdAt", + "email", + "name", + ]); + expect(user?.fields[0]?.isPrimaryKey).toBe(true); + expect(user?.fields[0]?.type).toBe("uuid"); + + const createdAt = user?.fields.find((field) => field.name === "createdAt"); + expect(createdAt?.defaultValue).toBe("now()"); + }); + + it("returns an empty snapshot for malformed documents", () => { + expect(parseContractSnapshot(null).models.size).toBe(0); + expect(parseContractSnapshot("garbage").models.size).toBe(0); + expect(parseContractSnapshot({ domain: 42 }).models.size).toBe(0); + }); +}); + +describe("diffContracts", () => { + it("marks every model and enum as added for a baseline migration", () => { + const diff = diffContracts( + null, + makeContract({ + models: { User: baseUser }, + enums: { Priority: ["low", "high"] }, + }), + ); + + expect(diff.models).toHaveLength(1); + expect(diff.models[0]?.status).toBe("added"); + expect(diff.enums[0]?.status).toBe("added"); + expect(diff.stats.modelsAdded).toBe(1); + expect(diff.stats.enumsAdded).toBe(1); + }); + + it("detects an added model without counting its fields as field additions", () => { + const before = makeContract({ models: { User: baseUser } }); + const after = makeContract({ + models: { + User: baseUser, + Post: { + fields: { + id: { codec: "pg/uuid@1", nativeType: "uuid" }, + title: {}, + }, + }, + }, + }); + + const diff = diffContracts(before, after); + const post = diff.models.find((model) => model.name === "Post"); + + expect(post?.status).toBe("added"); + expect(diff.stats.modelsAdded).toBe(1); + expect(diff.stats.fieldsAdded).toBe(0); + }); + + it("detects a removed model", () => { + const before = makeContract({ + models: { + User: baseUser, + AuditLog: { fields: { id: { codec: "pg/uuid@1" } } }, + }, + }); + const after = makeContract({ models: { User: baseUser } }); + + const diff = diffContracts(before, after); + const auditLog = diff.models.find((model) => model.name === "AuditLog"); + + expect(auditLog?.status).toBe("removed"); + expect(diff.stats.modelsRemoved).toBe(1); + }); + + it("detects added and removed fields on a changed model", () => { + const before = makeContract({ models: { User: baseUser } }); + const after = makeContract({ + models: { + User: { + ...baseUser, + fields: { + id: baseUser.fields.id as FieldSpec, + email: {}, + bio: { nullable: true }, + }, + }, + }, + }); + + const diff = diffContracts(before, after); + const user = diff.models.find((model) => model.name === "User"); + + expect(user?.status).toBe("changed"); + expect(user?.fields.find((field) => field.name === "bio")?.status).toBe( + "added", + ); + expect(user?.fields.find((field) => field.name === "name")?.status).toBe( + "removed", + ); + expect(diff.stats.fieldsAdded).toBe(1); + expect(diff.stats.fieldsRemoved).toBe(1); + }); + + it("reports how a field changed (type, nullability, default)", () => { + const before = makeContract({ + models: { + Task: { + fields: { + id: { codec: "pg/uuid@1", nativeType: "uuid" }, + status: { defaultValue: "open" }, + dueAt: { + codec: "pg/timestamptz@1", + nativeType: "timestamptz", + }, + }, + }, + }, + }); + const after = makeContract({ + models: { + Task: { + fields: { + id: { codec: "pg/uuid@1", nativeType: "uuid" }, + status: { defaultValue: "todo" }, + dueAt: { + codec: "pg/timestamptz@1", + nativeType: "timestamptz", + nullable: true, + }, + }, + }, + }, + }); + + const diff = diffContracts(before, after); + const task = diff.models.find((model) => model.name === "Task"); + const status = task?.fields.find((field) => field.name === "status"); + const dueAt = task?.fields.find((field) => field.name === "dueAt"); + + expect(status?.status).toBe("changed"); + expect(status?.details).toEqual([ + { aspect: "default", before: '"open"', after: '"todo"' }, + ]); + expect(dueAt?.status).toBe("changed"); + expect(dueAt?.details).toEqual([ + { aspect: "nullable", before: "required", after: "optional" }, + ]); + expect(diff.stats.fieldsChanged).toBe(2); + }); + + it("detects index and unique changes", () => { + const before = makeContract({ models: { User: baseUser } }); + const after = makeContract({ + models: { + User: { ...baseUser, uniques: [["email"]], indexes: [["name"]] }, + }, + }); + + const diff = diffContracts(before, after); + const user = diff.models.find((model) => model.name === "User"); + + expect(user?.status).toBe("changed"); + expect(user?.addedIndexes).toEqual(["index(name)", "unique(email)"]); + expect(diff.stats.indexesAdded).toBe(2); + }); + + it("diffs enum members", () => { + const before = makeContract({ + models: { User: baseUser }, + enums: { Priority: ["low", "high"] }, + }); + const after = makeContract({ + models: { User: baseUser }, + enums: { Priority: ["low", "medium", "high"] }, + }); + + const diff = diffContracts(before, after); + const priority = diff.enums.find((value) => value.name === "Priority"); + + expect(priority?.status).toBe("changed"); + expect( + priority?.members.find((member) => member.name === "medium")?.status, + ).toBe("added"); + }); + + it("detects added relations", () => { + const before = makeContract({ + models: { User: baseUser, Post: { fields: { id: {} } } }, + }); + const after = makeContract({ + models: { + User: baseUser, + Post: { + fields: { id: {}, authorId: { codec: "pg/uuid@1" } }, + relations: { author: { toModel: "User" } }, + }, + }, + }); + + const diff = diffContracts(before, after); + const post = diff.models.find((model) => model.name === "Post"); + + expect(post?.addedRelations).toHaveLength(1); + expect(post?.addedRelations[0]?.toModel).toBe("User"); + }); + + it("keeps a model unchanged when it only gains a back-relation", () => { + const before = makeContract({ models: { User: baseUser } }); + const after = makeContract({ + models: { + User: { + ...baseUser, + relations: { projects: { toModel: "Project", cardinality: "1:N" } }, + }, + Project: { + fields: { + id: { codec: "pg/uuid@1", nativeType: "uuid" }, + ownerId: { codec: "pg/uuid@1", nativeType: "uuid" }, + }, + relations: { owner: { toModel: "User" } }, + }, + }, + }); + + const diff = diffContracts(before, after); + const user = diff.models.find((model) => model.name === "User"); + + expect(user?.status).toBe("unchanged"); + expect(user?.addedRelations).toHaveLength(1); + expect(diff.stats.modelsChanged).toBe(0); + expect(diff.stats.modelsAdded).toBe(1); + }); + + it("leaves untouched models unchanged", () => { + const contract = makeContract({ + models: { User: baseUser, Post: { fields: { id: {} } } }, + }); + + const diff = diffContracts(contract, contract); + + expect(diff.models.every((model) => model.status === "unchanged")).toBe( + true, + ); + expect(diff.stats.modelsChanged).toBe(0); + }); +}); + +describe("summarizeDiff", () => { + it("renders compact chips for the changed dimensions", () => { + const diff = diffContracts( + makeContract({ models: { User: baseUser } }), + makeContract({ + models: { + User: { ...baseUser, uniques: [["email"]] }, + Post: { fields: { id: {} } }, + }, + enums: { Priority: ["low"] }, + }), + ); + + expect(summarizeDiff(diff.stats)).toEqual([ + "+1 model", + "~1 model", + "+1 enum", + "+1 index", + ]); + }); +}); diff --git a/ui/studio/views/migrations/contract-diff.ts b/ui/studio/views/migrations/contract-diff.ts new file mode 100644 index 00000000..f8258dce --- /dev/null +++ b/ui/studio/views/migrations/contract-diff.ts @@ -0,0 +1,701 @@ +/** + * Model-level diff engine for Prisma Next contract snapshots. + * + * A Prisma Next migration ledger row carries the full contract JSON + * before and after the migration (`contract_json_before` / + * `contract_json_after`). This module normalizes those documents into + * flat snapshots and diffs them into the structure the Migrations view + * renders: models added/removed/changed, per-field change details, + * enums, relations and index changes. + */ + +export interface SnapshotField { + name: string; + column: string | null; + type: string; + nullable: boolean; + defaultValue: string | null; + enumName: string | null; + isPrimaryKey: boolean; +} + +export interface SnapshotRelation { + name: string; + toModel: string; + cardinality: string; +} + +export interface SnapshotModel { + name: string; + table: string | null; + fields: SnapshotField[]; + relations: SnapshotRelation[]; + indexes: string[]; +} + +export interface SnapshotEnum { + name: string; + members: string[]; +} + +export interface ContractSnapshot { + models: Map; + enums: Map; +} + +export type DiffStatus = "added" | "removed" | "changed" | "unchanged"; + +export interface FieldChangeDetail { + aspect: "type" | "nullable" | "default" | "key"; + before: string; + after: string; +} + +export interface FieldDiff { + name: string; + status: DiffStatus; + field: SnapshotField; + details: FieldChangeDetail[]; +} + +export interface ModelDiff { + name: string; + status: DiffStatus; + table: string | null; + fields: FieldDiff[]; + addedIndexes: string[]; + removedIndexes: string[]; + addedRelations: SnapshotRelation[]; + removedRelations: SnapshotRelation[]; + relations: SnapshotRelation[]; +} + +export interface EnumDiff { + name: string; + status: DiffStatus; + members: Array<{ name: string; status: DiffStatus }>; +} + +export interface MigrationDiffStats { + modelsAdded: number; + modelsRemoved: number; + modelsChanged: number; + fieldsAdded: number; + fieldsRemoved: number; + fieldsChanged: number; + enumsAdded: number; + enumsRemoved: number; + indexesAdded: number; + indexesRemoved: number; +} + +export interface MigrationDiff { + models: ModelDiff[]; + enums: EnumDiff[]; + stats: MigrationDiffStats; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function asString(value: unknown): string | null { + return typeof value === "string" ? value : null; +} + +function codecToFriendlyType(codecId: string | null): string { + if (!codecId) { + return "unknown"; + } + + const match = /^[^/]+\/([^@]+)@/.exec(codecId); + + return match?.[1] ?? codecId; +} + +function renderDefault(value: unknown): string | null { + if (!isRecord(value)) { + return null; + } + + if (value.kind === "function") { + return asString(value.expression); + } + + if (value.kind === "literal") { + if (typeof value.value === "string") { + return `"${value.value}"`; + } + + return JSON.stringify(value.value ?? null); + } + + return null; +} + +interface StorageColumn { + nativeType: string | null; + nullable: boolean; + defaultValue: string | null; + codecId: string | null; +} + +interface StorageTable { + columns: Map; + primaryKeyColumns: Set; + indexes: string[]; +} + +function renderIndexSignature(prefix: string, value: unknown): string | null { + if (!isRecord(value) || !Array.isArray(value.columns)) { + return null; + } + + const columns = value.columns.filter( + (column): column is string => typeof column === "string", + ); + + if (columns.length === 0) { + return null; + } + + return `${prefix}(${columns.join(", ")})`; +} + +function parseStorageTables(contract: unknown): Map { + const tables = new Map(); + + if (!isRecord(contract)) { + return tables; + } + + const storage = contract.storage; + + if (!isRecord(storage) || !isRecord(storage.namespaces)) { + return tables; + } + + for (const namespace of Object.values(storage.namespaces)) { + if (!isRecord(namespace) || !isRecord(namespace.entries)) { + continue; + } + + const tableEntries = namespace.entries.table; + + if (!isRecord(tableEntries)) { + continue; + } + + for (const [tableName, table] of Object.entries(tableEntries)) { + if (!isRecord(table)) { + continue; + } + + const columns = new Map(); + + if (isRecord(table.columns)) { + for (const [columnName, column] of Object.entries(table.columns)) { + if (!isRecord(column)) { + continue; + } + + columns.set(columnName, { + nativeType: asString(column.nativeType), + nullable: column.nullable === true, + defaultValue: renderDefault(column.default), + codecId: asString(column.codecId), + }); + } + } + + const primaryKeyColumns = new Set(); + + if ( + isRecord(table.primaryKey) && + Array.isArray(table.primaryKey.columns) + ) { + for (const column of table.primaryKey.columns) { + if (typeof column === "string") { + primaryKeyColumns.add(column); + } + } + } + + const indexes: string[] = []; + + if (Array.isArray(table.indexes)) { + for (const index of table.indexes) { + const signature = renderIndexSignature("index", index); + + if (signature) { + indexes.push(signature); + } + } + } + + if (Array.isArray(table.uniques)) { + for (const unique of table.uniques) { + const signature = renderIndexSignature("unique", unique); + + if (signature) { + indexes.push(signature); + } + } + } + + tables.set(tableName, { columns, primaryKeyColumns, indexes }); + } + } + + return tables; +} + +/** + * Normalizes a Prisma Next contract JSON document into a flat snapshot + * of models and enums. Unknown or malformed documents produce an empty + * snapshot rather than throwing. + */ +export function parseContractSnapshot(contract: unknown): ContractSnapshot { + const models = new Map(); + const enums = new Map(); + + if (!isRecord(contract)) { + return { models, enums }; + } + + const storageTables = parseStorageTables(contract); + const domain = contract.domain; + + if (!isRecord(domain) || !isRecord(domain.namespaces)) { + return { models, enums }; + } + + for (const namespace of Object.values(domain.namespaces)) { + if (!isRecord(namespace)) { + continue; + } + + if (isRecord(namespace.enum)) { + for (const [enumName, enumValue] of Object.entries(namespace.enum)) { + if (!isRecord(enumValue) || !Array.isArray(enumValue.members)) { + continue; + } + + const members = enumValue.members + .map((member) => (isRecord(member) ? asString(member.name) : null)) + .filter((member): member is string => member !== null); + + enums.set(enumName, { name: enumName, members }); + } + } + + if (!isRecord(namespace.models)) { + continue; + } + + for (const [modelName, model] of Object.entries(namespace.models)) { + if (!isRecord(model)) { + continue; + } + + const modelStorage = isRecord(model.storage) ? model.storage : {}; + const table = asString(modelStorage.table); + const storageTable = table ? storageTables.get(table) : undefined; + const fieldColumns = isRecord(modelStorage.fields) + ? modelStorage.fields + : {}; + + const fields: SnapshotField[] = []; + + if (isRecord(model.fields)) { + for (const [fieldName, field] of Object.entries(model.fields)) { + if (!isRecord(field)) { + continue; + } + + const columnMapping = fieldColumns[fieldName]; + const column = isRecord(columnMapping) + ? asString(columnMapping.column) + : null; + const storageColumn = column + ? storageTable?.columns.get(column) + : undefined; + const fieldType = isRecord(field.type) ? field.type : {}; + const valueSet = isRecord(field.valueSet) ? field.valueSet : null; + const enumName = valueSet ? asString(valueSet.entityName) : null; + + fields.push({ + name: fieldName, + column, + type: + enumName ?? + storageColumn?.nativeType ?? + codecToFriendlyType(asString(fieldType.codecId)), + nullable: storageColumn?.nullable ?? field.nullable === true, + defaultValue: storageColumn?.defaultValue ?? null, + enumName, + isPrimaryKey: + column !== null && + (storageTable?.primaryKeyColumns.has(column) ?? false), + }); + } + } + + fields.sort((left, right) => { + if (left.isPrimaryKey !== right.isPrimaryKey) { + return left.isPrimaryKey ? -1 : 1; + } + + return left.name.localeCompare(right.name); + }); + + const relations: SnapshotRelation[] = []; + + if (isRecord(model.relations)) { + for (const [relationName, relation] of Object.entries( + model.relations, + )) { + if (!isRecord(relation)) { + continue; + } + + const to = isRecord(relation.to) ? relation.to : null; + const toModel = to ? asString(to.model) : null; + + if (!toModel) { + continue; + } + + relations.push({ + name: relationName, + toModel, + cardinality: asString(relation.cardinality) ?? "1:N", + }); + } + } + + relations.sort((left, right) => left.name.localeCompare(right.name)); + + models.set(modelName, { + name: modelName, + table, + fields, + relations, + indexes: storageTable ? [...storageTable.indexes].sort() : [], + }); + } + } + + return { models, enums }; +} + +function describeNullable(nullable: boolean): string { + return nullable ? "optional" : "required"; +} + +function diffFields( + before: SnapshotModel | undefined, + after: SnapshotModel | undefined, +): FieldDiff[] { + const beforeFields = new Map( + (before?.fields ?? []).map((field) => [field.name, field]), + ); + const afterFields = new Map( + (after?.fields ?? []).map((field) => [field.name, field]), + ); + const names = [...new Set([...beforeFields.keys(), ...afterFields.keys()])]; + const diffs: FieldDiff[] = []; + + for (const name of names) { + const fieldBefore = beforeFields.get(name); + const fieldAfter = afterFields.get(name); + + if (fieldBefore && !fieldAfter) { + diffs.push({ name, status: "removed", field: fieldBefore, details: [] }); + continue; + } + + if (!fieldBefore && fieldAfter) { + diffs.push({ name, status: "added", field: fieldAfter, details: [] }); + continue; + } + + if (!fieldBefore || !fieldAfter) { + continue; + } + + const details: FieldChangeDetail[] = []; + + if (fieldBefore.type !== fieldAfter.type) { + details.push({ + aspect: "type", + before: fieldBefore.type, + after: fieldAfter.type, + }); + } + + if (fieldBefore.nullable !== fieldAfter.nullable) { + details.push({ + aspect: "nullable", + before: describeNullable(fieldBefore.nullable), + after: describeNullable(fieldAfter.nullable), + }); + } + + if (fieldBefore.defaultValue !== fieldAfter.defaultValue) { + details.push({ + aspect: "default", + before: fieldBefore.defaultValue ?? "none", + after: fieldAfter.defaultValue ?? "none", + }); + } + + if (fieldBefore.isPrimaryKey !== fieldAfter.isPrimaryKey) { + details.push({ + aspect: "key", + before: fieldBefore.isPrimaryKey ? "@id" : "plain", + after: fieldAfter.isPrimaryKey ? "@id" : "plain", + }); + } + + diffs.push({ + name, + status: details.length > 0 ? "changed" : "unchanged", + field: fieldAfter, + details, + }); + } + + const order = (status: DiffStatus): number => + status === "added" + ? 0 + : status === "changed" + ? 1 + : status === "removed" + ? 2 + : 3; + + return diffs.sort((left, right) => { + const statusDelta = order(left.status) - order(right.status); + + if (statusDelta !== 0) { + return statusDelta; + } + + if (left.field.isPrimaryKey !== right.field.isPrimaryKey) { + return left.field.isPrimaryKey ? -1 : 1; + } + + return left.name.localeCompare(right.name); + }); +} + +function relationKey(relation: SnapshotRelation): string { + return `${relation.name}→${relation.toModel}:${relation.cardinality}`; +} + +/** + * Diffs two contract snapshots into the render model for the visual + * migration diff. Passing `null` for the before document treats every + * model and enum as newly added (a baseline migration). + */ +export function diffContracts( + contractBefore: unknown, + contractAfter: unknown, +): MigrationDiff { + const before = parseContractSnapshot(contractBefore); + const after = parseContractSnapshot(contractAfter); + + const modelNames = [ + ...new Set([...before.models.keys(), ...after.models.keys()]), + ].sort(); + const models: ModelDiff[] = []; + + for (const name of modelNames) { + const modelBefore = before.models.get(name); + const modelAfter = after.models.get(name); + const fields = diffFields(modelBefore, modelAfter); + const beforeIndexes = new Set(modelBefore?.indexes ?? []); + const afterIndexes = new Set(modelAfter?.indexes ?? []); + const addedIndexes = [...afterIndexes].filter( + (index) => !beforeIndexes.has(index), + ); + const removedIndexes = [...beforeIndexes].filter( + (index) => !afterIndexes.has(index), + ); + const beforeRelations = new Map( + (modelBefore?.relations ?? []).map((relation) => [ + relationKey(relation), + relation, + ]), + ); + const afterRelations = new Map( + (modelAfter?.relations ?? []).map((relation) => [ + relationKey(relation), + relation, + ]), + ); + const addedRelations = [...afterRelations.entries()] + .filter(([key]) => !beforeRelations.has(key)) + .map(([, relation]) => relation); + const removedRelations = [...beforeRelations.entries()] + .filter(([key]) => !afterRelations.has(key)) + .map(([, relation]) => relation); + + let status: DiffStatus; + + if (modelBefore && !modelAfter) { + status = "removed"; + } else if (!modelBefore && modelAfter) { + status = "added"; + } else { + const hasFieldChanges = fields.some( + (field) => field.status !== "unchanged", + ); + // Relation changes alone don't flip a model to "changed": a + // back-relation is stored via the other table's foreign key, so + // the model's own table is untouched. Relation additions still + // surface through emphasized edges on the canvas. + const hasStorageChanges = + addedIndexes.length > 0 || removedIndexes.length > 0; + + status = hasFieldChanges || hasStorageChanges ? "changed" : "unchanged"; + } + + models.push({ + name, + status, + table: modelAfter?.table ?? modelBefore?.table ?? null, + fields, + addedIndexes, + removedIndexes, + addedRelations, + removedRelations, + relations: modelAfter?.relations ?? modelBefore?.relations ?? [], + }); + } + + const enumNames = [ + ...new Set([...before.enums.keys(), ...after.enums.keys()]), + ].sort(); + const enums: EnumDiff[] = []; + + for (const name of enumNames) { + const enumBefore = before.enums.get(name); + const enumAfter = after.enums.get(name); + const beforeMembers = new Set(enumBefore?.members ?? []); + const afterMembers = new Set(enumAfter?.members ?? []); + const memberNames = [...new Set([...beforeMembers, ...afterMembers])]; + const members = memberNames.map((member) => ({ + name: member, + status: + beforeMembers.has(member) && afterMembers.has(member) + ? ("unchanged" as const) + : afterMembers.has(member) + ? ("added" as const) + : ("removed" as const), + })); + + const status: DiffStatus = + enumBefore && !enumAfter + ? "removed" + : !enumBefore && enumAfter + ? "added" + : members.some((member) => member.status !== "unchanged") + ? "changed" + : "unchanged"; + + enums.push({ name, status, members }); + } + + const stats: MigrationDiffStats = { + modelsAdded: models.filter((model) => model.status === "added").length, + modelsRemoved: models.filter((model) => model.status === "removed").length, + modelsChanged: models.filter((model) => model.status === "changed").length, + fieldsAdded: models + .filter((model) => model.status !== "added") + .reduce( + (sum, model) => + sum + model.fields.filter((field) => field.status === "added").length, + 0, + ), + fieldsRemoved: models + .filter((model) => model.status !== "removed") + .reduce( + (sum, model) => + sum + + model.fields.filter((field) => field.status === "removed").length, + 0, + ), + fieldsChanged: models.reduce( + (sum, model) => + sum + model.fields.filter((field) => field.status === "changed").length, + 0, + ), + enumsAdded: enums.filter((value) => value.status === "added").length, + enumsRemoved: enums.filter((value) => value.status === "removed").length, + indexesAdded: models.reduce( + (sum, model) => sum + model.addedIndexes.length, + 0, + ), + indexesRemoved: models.reduce( + (sum, model) => sum + model.removedIndexes.length, + 0, + ), + }; + + return { models, enums, stats }; +} + +/** + * Summarizes a diff into short human chips, e.g. `["+2 models", "~1 model"]`. + */ +export function summarizeDiff(stats: MigrationDiffStats): string[] { + const chips: string[] = []; + const pluralize = (count: number, noun: string) => + count === 1 + ? `${count} ${noun}` + : `${count} ${noun === "index" ? "indexes" : `${noun}s`}`; + + if (stats.modelsAdded > 0) { + chips.push(`+${pluralize(stats.modelsAdded, "model")}`); + } + + if (stats.modelsRemoved > 0) { + chips.push(`−${pluralize(stats.modelsRemoved, "model")}`); + } + + if (stats.modelsChanged > 0) { + chips.push(`~${pluralize(stats.modelsChanged, "model")}`); + } + + if (stats.fieldsAdded > 0) { + chips.push(`+${pluralize(stats.fieldsAdded, "field")}`); + } + + if (stats.fieldsRemoved > 0) { + chips.push(`−${pluralize(stats.fieldsRemoved, "field")}`); + } + + if (stats.fieldsChanged > 0) { + chips.push(`~${pluralize(stats.fieldsChanged, "field")}`); + } + + if (stats.enumsAdded > 0) { + chips.push(`+${pluralize(stats.enumsAdded, "enum")}`); + } + + if (stats.enumsRemoved > 0) { + chips.push(`−${pluralize(stats.enumsRemoved, "enum")}`); + } + + if (stats.indexesAdded > 0) { + chips.push(`+${pluralize(stats.indexesAdded, "index")}`); + } + + if (stats.indexesRemoved > 0) { + chips.push(`−${pluralize(stats.indexesRemoved, "index")}`); + } + + return chips; +} diff --git a/ui/studio/views/migrations/diff-layout.test.ts b/ui/studio/views/migrations/diff-layout.test.ts new file mode 100644 index 00000000..5d3560c7 --- /dev/null +++ b/ui/studio/views/migrations/diff-layout.test.ts @@ -0,0 +1,148 @@ +import { describe, expect, it } from "vitest"; + +import type { EnumDiff, MigrationDiff, ModelDiff } from "./contract-diff"; +import { buildDiffGraph } from "./diff-layout"; + +function model( + name: string, + overrides: Partial = {}, +): ModelDiff { + return { + name, + status: "unchanged", + table: name.toLowerCase(), + fields: [], + addedIndexes: [], + removedIndexes: [], + addedRelations: [], + removedRelations: [], + relations: [], + ...overrides, + }; +} + +function enumDiff( + name: string, + overrides: Partial = {}, +): EnumDiff { + return { + name, + status: "unchanged", + members: [{ name: "low", status: "unchanged" }], + ...overrides, + }; +} + +function diff(models: ModelDiff[], enums: EnumDiff[] = []): MigrationDiff { + return { + models, + enums, + stats: { + modelsAdded: 0, + modelsRemoved: 0, + modelsChanged: 0, + fieldsAdded: 0, + fieldsRemoved: 0, + fieldsChanged: 0, + enumsAdded: 0, + enumsRemoved: 0, + indexesAdded: 0, + indexesRemoved: 0, + }, + }; +} + +function nodeIds(graph: { nodes: Array<{ id: string }> }): string[] { + return graph.nodes.map((node) => node.id).sort(); +} + +describe("buildDiffGraph", () => { + const migration = diff( + [ + model("Comment", { + status: "added", + relations: [ + { name: "task", toModel: "Task", cardinality: "N:1" }, + { name: "author", toModel: "User", cardinality: "N:1" }, + ], + }), + model("Task"), + model("User"), + model("Tag"), + ], + [enumDiff("Priority")], + ); + + it("scopes to touched models, their neighbors, and touched enums by default", () => { + const graph = buildDiffGraph(migration, false); + + expect(nodeIds(graph)).toEqual([ + "model:Comment", + "model:Task", + "model:User", + ]); + }); + + it("includes every model and unchanged enums when showing all models", () => { + const graph = buildDiffGraph(migration, true); + + expect(nodeIds(graph)).toEqual([ + "enum:Priority", + "model:Comment", + "model:Tag", + "model:Task", + "model:User", + ]); + }); + + it("always includes touched enums, even in the scoped view", () => { + const graph = buildDiffGraph( + diff( + [model("Task", { status: "changed" })], + [enumDiff("TaskStatus", { status: "added" }), enumDiff("Priority")], + ), + false, + ); + + expect(nodeIds(graph)).toEqual(["enum:TaskStatus", "model:Task"]); + }); + + it("treats a relation-only model as touched for scoping without amber status", () => { + const graph = buildDiffGraph( + diff([ + model("User", { + addedRelations: [ + { name: "projects", toModel: "Project", cardinality: "1:N" }, + ], + relations: [ + { name: "projects", toModel: "Project", cardinality: "1:N" }, + ], + }), + model("Project", { status: "added" }), + model("Tag"), + ]), + false, + ); + + expect(nodeIds(graph)).toEqual(["model:Project", "model:User"]); + + const edge = graph.edges.find((candidate) => + candidate.id.includes("Project"), + ); + + expect(edge?.animated).toBe(true); + }); + + it("falls back to the full schema when a migration touches nothing", () => { + const graph = buildDiffGraph( + diff([model("User"), model("Tag")], [enumDiff("Priority")]), + false, + ); + + expect(nodeIds(graph)).toEqual([ + "enum:Priority", + "model:Tag", + "model:User", + ]); + }); +}); diff --git a/ui/studio/views/migrations/diff-layout.ts b/ui/studio/views/migrations/diff-layout.ts new file mode 100644 index 00000000..b258088b --- /dev/null +++ b/ui/studio/views/migrations/diff-layout.ts @@ -0,0 +1,287 @@ +import ELK from "elkjs/lib/elk.bundled.js"; +import type { Edge, Node } from "reactflow"; +import { Position } from "reactflow"; + +import type { EnumDiff, MigrationDiff, ModelDiff } from "./contract-diff"; + +const elk = new ELK(); + +const ELK_LAYOUT_OPTIONS = { + "elk.algorithm": "layered", + "elk.direction": "RIGHT", + "elk.edgeRouting": "SPLINES", + "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX", + "elk.layered.spacing.nodeNodeBetweenLayers": "120", + "elk.spacing.nodeNode": "70", +} as const; + +const NODE_WIDTH = 264; +const NODE_HEADER_HEIGHT = 52; +const NODE_ROW_HEIGHT = 26; +const NODE_DETAIL_ROW_HEIGHT = 20; +const NODE_CHIP_ROW_HEIGHT = 26; +const NODE_VERTICAL_PADDING = 24; +const ENUM_NODE_WIDTH = 190; + +export interface ModelDiffNodeData { + model: ModelDiff; +} + +export interface EnumDiffNodeData { + enumDiff: EnumDiff; +} + +export type MigrationDiffNode = + | Node + | Node; + +export function estimateModelNodeHeight(model: ModelDiff): number { + const detailRows = model.fields.reduce( + (sum, field) => sum + field.details.length, + 0, + ); + const chipRows = + model.addedIndexes.length + + model.removedIndexes.length + + model.addedRelations.length + + model.removedRelations.length > + 0 + ? 1 + : 0; + + return ( + NODE_HEADER_HEIGHT + + model.fields.length * NODE_ROW_HEIGHT + + detailRows * NODE_DETAIL_ROW_HEIGHT + + chipRows * NODE_CHIP_ROW_HEIGHT + + NODE_VERTICAL_PADDING + ); +} + +export function estimateEnumNodeHeight(enumDiff: EnumDiff): number { + return ( + NODE_HEADER_HEIGHT + + enumDiff.members.length * NODE_ROW_HEIGHT + + NODE_VERTICAL_PADDING + ); +} + +function estimateNodeSize(node: MigrationDiffNode): { + height: number; + width: number; +} { + if (node.type === "enumDiff") { + const data = node.data as EnumDiffNodeData; + + return { + height: estimateEnumNodeHeight(data.enumDiff), + width: ENUM_NODE_WIDTH, + }; + } + + const data = node.data as ModelDiffNodeData; + + return { + height: estimateModelNodeHeight(data.model), + width: NODE_WIDTH, + }; +} + +export function createModelDiffNode(model: ModelDiff): MigrationDiffNode { + return { + data: { model }, + id: `model:${model.name}`, + position: { x: 0, y: 0 }, + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "modelDiff", + }; +} + +export function createEnumDiffNode(enumDiff: EnumDiff): MigrationDiffNode { + return { + data: { enumDiff }, + id: `enum:${enumDiff.name}`, + position: { x: 0, y: 0 }, + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "enumDiff", + }; +} + +/** + * Builds the React Flow graph for a migration diff. + * + * Default scope is the migration's story: touched models (their own + * table changed, or a relation was added/removed), their direct + * relation neighbors as dimmed context, and touched enums. + * `showAllModels` widens the scope to every model and enum in the + * migration's contract — unchanged ones render in the dimmed context + * style. + */ +export function buildDiffGraph( + diff: MigrationDiff, + showAllModels: boolean, +): { + nodes: MigrationDiffNode[]; + edges: Edge[]; +} { + const isTouched = (model: MigrationDiff["models"][number]) => + model.status !== "unchanged" || + model.addedRelations.length > 0 || + model.removedRelations.length > 0; + const touchedModels = diff.models.filter(isTouched); + const touchedNames = new Set(touchedModels.map((model) => model.name)); + const contextNames = new Set(); + + for (const model of touchedModels) { + for (const relation of [...model.relations, ...model.removedRelations]) { + if (!touchedNames.has(relation.toModel)) { + contextNames.add(relation.toModel); + } + } + } + + for (const model of diff.models) { + if (touchedNames.has(model.name)) { + continue; + } + + if ( + model.relations.some((relation) => touchedNames.has(relation.toModel)) + ) { + contextNames.add(model.name); + } + } + + const showEverything = showAllModels || touchedModels.length === 0; + const visibleModels = showEverything + ? diff.models + : diff.models.filter( + (model) => touchedNames.has(model.name) || contextNames.has(model.name), + ); + const visibleNames = new Set(visibleModels.map((model) => model.name)); + const visibleEnums = showEverything + ? diff.enums + : diff.enums.filter((enumDiff) => enumDiff.status !== "unchanged"); + + const nodes: MigrationDiffNode[] = [ + ...visibleModels.map((model) => createModelDiffNode(model)), + ...visibleEnums.map((enumDiff) => createEnumDiffNode(enumDiff)), + ]; + + const edges: Edge[] = []; + // A relation is listed on both of its models (forward + back-relation), + // so per model pair only the first-encountered side draws its edges — + // but it draws ALL of them, keyed by relation name, so two distinct + // relations to the same model stay two edges. Removed relations get + // their own ownership so a drop still renders when only the far side + // remembers it. + const pairOwners = new Map(); + + for (const model of visibleModels) { + const relationEntries = [ + ...model.relations.map((relation) => ({ relation, removed: false })), + ...model.removedRelations.map((relation) => ({ + relation, + removed: true, + })), + ]; + + for (const { relation, removed } of relationEntries) { + if (!visibleNames.has(relation.toModel)) { + continue; + } + + const pairKey = [model.name, relation.toModel].sort().join("↔"); + const ownerKey = `${pairKey}|${removed ? "removed" : "live"}`; + const owner = pairOwners.get(ownerKey); + + if (owner !== undefined && owner !== model.name) { + continue; + } + + pairOwners.set(ownerKey, model.name); + + const added = model.addedRelations.some( + (candidate) => + candidate.name === relation.name && + candidate.toModel === relation.toModel, + ); + + edges.push({ + id: `relation:${pairKey}:${removed ? "removed:" : ""}${relation.name}`, + source: `model:${model.name}`, + target: `model:${relation.toModel}`, + label: relation.cardinality, + labelStyle: { fontSize: 10, fill: "var(--muted-foreground)" }, + labelBgStyle: { fill: "var(--background)", fillOpacity: 0.8 }, + animated: added, + style: { + stroke: removed + ? "var(--destructive)" + : added + ? "oklch(0.7 0.15 160)" + : "var(--muted-foreground)", + strokeDasharray: removed ? "3 3" : added ? undefined : "5 5", + strokeWidth: added || removed ? 2 : 1, + opacity: removed ? 0.7 : 0.9, + }, + type: "default", + }); + } + } + + return { nodes, edges }; +} + +export async function layoutMigrationDiffNodes( + nodes: MigrationDiffNode[], + edges: Pick[], +): Promise { + if (nodes.length <= 1) { + return nodes; + } + + try { + const layouted = await elk.layout({ + id: "root", + layoutOptions: { ...ELK_LAYOUT_OPTIONS }, + children: nodes.map((node) => ({ + id: node.id, + ...estimateNodeSize(node), + })), + edges: edges.map((edge) => ({ + id: edge.id, + sources: [edge.source], + targets: [edge.target], + })), + }); + + const positions = new Map( + (layouted.children ?? []).map((child) => [ + child.id, + { x: child.x ?? 0, y: child.y ?? 0 }, + ]), + ); + + return nodes.map((node) => ({ + ...node, + position: positions.get(node.id) ?? node.position, + })); + } catch (error) { + console.warn( + "[migrations] ELK layout failed; falling back to grid placement", + error, + ); + const columns = Math.max(1, Math.ceil(Math.sqrt(nodes.length))); + + return nodes.map((node, index) => ({ + ...node, + position: { + x: (index % columns) * (NODE_WIDTH + 90), + y: Math.floor(index / columns) * 360, + }, + })); + } +} diff --git a/ui/studio/views/migrations/psl-schema.test.ts b/ui/studio/views/migrations/psl-schema.test.ts new file mode 100644 index 00000000..59ad7da5 --- /dev/null +++ b/ui/studio/views/migrations/psl-schema.test.ts @@ -0,0 +1,198 @@ +import { describe, expect, it } from "vitest"; + +import { parseContractSnapshot } from "./contract-diff"; +import { + diffSchemas, + renderPslSchema, + schemaDiffHasChanges, +} from "./psl-schema"; + +function contract(overrides: { + models?: Record; + enums?: Record; + tables?: Record; +}): unknown { + return { + domain: { + namespaces: { + public: { + models: overrides.models ?? {}, + enum: overrides.enums ?? {}, + }, + }, + }, + storage: { + namespaces: { + public: { entries: { table: overrides.tables ?? {} }, id: "public" }, + }, + }, + }; +} + +const userContract = contract({ + models: { + User: { + fields: { + id: { + nullable: false, + type: { kind: "scalar", codecId: "pg/uuid@1" }, + }, + email: { + nullable: false, + type: { kind: "scalar", codecId: "pg/text@1" }, + }, + bio: { + nullable: true, + type: { kind: "scalar", codecId: "pg/text@1" }, + }, + kind: { + nullable: false, + type: { kind: "scalar", codecId: "pg/text@1" }, + valueSet: { + entityKind: "enum", + entityName: "UserKind", + namespaceId: "public", + plane: "domain", + }, + }, + }, + relations: { + posts: { + cardinality: "1:N", + to: { model: "Post", namespace: "public" }, + on: { localFields: ["id"], targetFields: ["userId"] }, + }, + }, + storage: { + fields: { + id: { column: "id" }, + email: { column: "email" }, + bio: { column: "bio" }, + kind: { column: "kind" }, + }, + namespaceId: "public", + table: "user", + }, + }, + }, + enums: { + UserKind: { + codecId: "pg/text@1", + members: [ + { name: "admin", value: "admin" }, + { name: "member", value: "member" }, + ], + }, + }, + tables: { + user: { + columns: { + id: { + codecId: "pg/uuid@1", + nativeType: "uuid", + nullable: false, + default: { kind: "function", expression: "gen_random_uuid()" }, + }, + email: { codecId: "pg/text@1", nativeType: "text", nullable: false }, + bio: { codecId: "pg/text@1", nativeType: "text", nullable: true }, + kind: { + codecId: "pg/text@1", + nativeType: "text", + nullable: false, + default: { kind: "literal", value: "member" }, + }, + }, + primaryKey: { columns: ["id"] }, + uniques: [{ columns: ["email"] }], + indexes: [], + foreignKeys: [], + }, + }, +}); + +describe("renderPslSchema", () => { + it("renders enums, models, fields, defaults, relations, and block attributes", () => { + const schema = renderPslSchema(parseContractSnapshot(userContract)); + + expect(schema).toBe( + [ + "enum UserKind {", + " admin", + " member", + "}", + "", + "model User {", + " id String @id @default(uuid()) @db.Uuid", + " bio String?", + " email String", + ' kind UserKind @default("member")', + "", + " posts Post[]", + "", + " @@unique([email])", + ' @@map("user")', + "}", + ].join("\n"), + ); + }); + + it("renders an empty snapshot as an empty schema", () => { + expect(renderPslSchema(parseContractSnapshot(null))).toBe(""); + }); +}); + +describe("diffSchemas", () => { + it("marks added and removed lines", () => { + const before = "model User {\n id String @id\n}"; + const after = "model User {\n id String @id\n bio String?\n}"; + + const lines = diffSchemas(before, after); + + expect(lines).toEqual([ + { kind: "context", text: "model User {" }, + { kind: "context", text: " id String @id" }, + { kind: "added", text: " bio String?" }, + { kind: "context", text: "}" }, + ]); + expect(schemaDiffHasChanges(lines)).toBe(true); + }); + + it("collapses long unchanged runs around the changes", () => { + const stable = Array.from({ length: 12 }, (_, i) => ` line${i}`); + const before = ["model A {", ...stable, "}"].join("\n"); + const after = ["model A {", ...stable, " extra Int", "}"].join("\n"); + + const lines = diffSchemas(before, after); + const collapsed = lines.find((line) => line.kind === "collapsed"); + + expect(collapsed?.hiddenCount).toBeGreaterThan(6); + expect(lines.filter((line) => line.kind === "added")).toHaveLength(1); + }); + + it("carries the folded lines so the view can expand a collapse in place", () => { + const stable = Array.from({ length: 12 }, (_, i) => ` line${i}`); + const before = ["model A {", ...stable, "}"].join("\n"); + const after = ["model A {", ...stable, " extra Int", "}"].join("\n"); + + const lines = diffSchemas(before, after); + const collapsed = lines.find((line) => line.kind === "collapsed"); + const visibleContext = lines + .filter((line) => line.kind === "context") + .map((line) => line.text); + + expect(collapsed?.hiddenLines).toHaveLength(collapsed?.hiddenCount ?? -1); + // The fold leads (first hunk keeps no leading context), so folded + + // visible context reassemble the full unchanged text, in order. + expect([...(collapsed?.hiddenLines ?? []), ...visibleContext]).toEqual([ + "model A {", + ...stable, + "}", + ]); + }); + + it("reports no changes for identical schemas", () => { + const schema = "model User {\n id String @id\n}"; + + expect(schemaDiffHasChanges(diffSchemas(schema, schema))).toBe(false); + }); +}); diff --git a/ui/studio/views/migrations/psl-schema.ts b/ui/studio/views/migrations/psl-schema.ts new file mode 100644 index 00000000..7491959b --- /dev/null +++ b/ui/studio/views/migrations/psl-schema.ts @@ -0,0 +1,268 @@ +import { diffLines } from "diff"; + +import type { ContractSnapshot, SnapshotModel } from "./contract-diff"; + +/** + * Renders a Prisma-schema-style view of a contract snapshot and diffs + * two snapshots line by line for the Migrations view's schema panel. + * + * The output is a faithful PSL-shaped projection of the contract (model + * and enum blocks, field types, defaults, relations, index/unique/map + * attributes), optimized for stable diffs: fields are consistently + * ordered and separated by single runs of spaces so adding one field + * never rewrites its neighbors. + */ + +const NATIVE_TYPE_TO_PSL: Record = { + uuid: { type: "String", native: "@db.Uuid" }, + text: { type: "String" }, + varchar: { type: "String", native: "@db.VarChar" }, + bool: { type: "Boolean" }, + boolean: { type: "Boolean" }, + int4: { type: "Int" }, + integer: { type: "Int" }, + int8: { type: "BigInt" }, + bigint: { type: "BigInt" }, + float8: { type: "Float" }, + numeric: { type: "Decimal" }, + timestamptz: { type: "DateTime" }, + timestamp: { type: "DateTime" }, + date: { type: "DateTime", native: "@db.Date" }, + jsonb: { type: "Json" }, + json: { type: "Json" }, + bytea: { type: "Bytes" }, +}; + +function pslDefault(defaultValue: string | null): string | null { + if (defaultValue === null) { + return null; + } + + if (defaultValue === "now()") { + return "@default(now())"; + } + + if (defaultValue === "gen_random_uuid()") { + return "@default(uuid())"; + } + + // Any other function-call expression (zero-arg like `now()` variants or + // parameterized like `nextval('seq'::regclass)`) is not valid bare PSL. + if (/^[A-Za-z_][\w.]*\(.*\)$/.test(defaultValue)) { + return `@default(dbgenerated("${defaultValue.replaceAll('"', '\\"')}"))`; + } + + return `@default(${defaultValue})`; +} + +function renderModel(model: SnapshotModel): string[] { + const lines: string[] = [`model ${model.name} {`]; + + for (const field of model.fields) { + const mapped = field.enumName + ? { type: field.enumName, native: undefined } + : (NATIVE_TYPE_TO_PSL[field.type] ?? { type: field.type }); + const attributes: string[] = []; + + if (field.isPrimaryKey) { + attributes.push("@id"); + } + + const renderedDefault = pslDefault(field.defaultValue); + + if (renderedDefault) { + attributes.push(renderedDefault); + } + + if (mapped.native) { + attributes.push(mapped.native); + } + + if (field.column && field.column !== field.name) { + attributes.push(`@map("${field.column}")`); + } + + const type = `${mapped.type}${field.nullable ? "?" : ""}`; + const suffix = attributes.length > 0 ? ` ${attributes.join(" ")}` : ""; + + lines.push(` ${field.name} ${type}${suffix}`); + } + + if (model.relations.length > 0) { + lines.push(""); + + for (const relation of model.relations) { + const isList = + relation.cardinality === "1:N" || relation.cardinality === "N:M"; + const type = isList ? `${relation.toModel}[]` : relation.toModel; + + lines.push(` ${relation.name} ${type}`); + } + } + + const blockAttributes: string[] = []; + + for (const index of model.indexes) { + const match = /^(index|unique)\((.+)\)$/.exec(index); + + if (!match) { + continue; + } + + const attribute = match[1] === "unique" ? "@@unique" : "@@index"; + const columns = (match[2] ?? "") + .split(",") + .map((column) => column.trim()) + .filter((column) => column.length > 0); + + blockAttributes.push(`${attribute}([${columns.join(", ")}])`); + } + + if (model.table && model.table !== model.name) { + blockAttributes.push(`@@map("${model.table}")`); + } + + if (blockAttributes.length > 0) { + lines.push(""); + + for (const attribute of blockAttributes) { + lines.push(` ${attribute}`); + } + } + + lines.push("}"); + + return lines; +} + +export function renderPslSchema(snapshot: ContractSnapshot): string { + const blocks: string[] = []; + const enumNames = [...snapshot.enums.keys()].sort(); + + for (const enumName of enumNames) { + const enumValue = snapshot.enums.get(enumName); + + if (!enumValue) { + continue; + } + + blocks.push( + [ + `enum ${enumName} {`, + ...enumValue.members.map((member) => ` ${member}`), + "}", + ].join("\n"), + ); + } + + const modelNames = [...snapshot.models.keys()].sort(); + + for (const modelName of modelNames) { + const model = snapshot.models.get(modelName); + + if (!model) { + continue; + } + + blocks.push(renderModel(model).join("\n")); + } + + return blocks.join("\n\n"); +} + +export type SchemaDiffLineKind = "added" | "removed" | "context" | "collapsed"; + +export interface SchemaDiffLine { + kind: SchemaDiffLineKind; + text: string; + /** Number of hidden lines when `kind` is "collapsed". */ + hiddenCount?: number; + /** + * The collapsed run's actual lines when `kind` is "collapsed", so the + * view can expand a fold in place without re-diffing. + */ + hiddenLines?: string[]; +} + +const CONTEXT_LINES = 2; + +/** + * Produces a unified line diff of two schema texts, collapsing long + * unchanged runs down to `CONTEXT_LINES` around each change. + */ +export function diffSchemas(before: string, after: string): SchemaDiffLine[] { + const parts = diffLines(before, after); + const lines: SchemaDiffLine[] = []; + + const pushAll = (kind: "added" | "removed", value: string) => { + for (const text of splitLines(value)) { + lines.push({ kind, text }); + } + }; + + for (let index = 0; index < parts.length; index += 1) { + const part = parts[index]; + + if (!part) { + continue; + } + + if (part.added) { + pushAll("added", part.value); + continue; + } + + if (part.removed) { + pushAll("removed", part.value); + continue; + } + + const contextLines = splitLines(part.value); + const isFirst = index === 0; + const isLast = index === parts.length - 1; + const leadingKeep = isFirst ? 0 : CONTEXT_LINES; + const trailingKeep = isLast ? 0 : CONTEXT_LINES; + + if (contextLines.length <= leadingKeep + trailingKeep + 1) { + for (const text of contextLines) { + lines.push({ kind: "context", text }); + } + continue; + } + + for (const text of contextLines.slice(0, leadingKeep)) { + lines.push({ kind: "context", text }); + } + + const hiddenCount = contextLines.length - leadingKeep - trailingKeep; + + lines.push({ + kind: "collapsed", + text: "", + hiddenCount, + hiddenLines: contextLines.slice(leadingKeep, leadingKeep + hiddenCount), + }); + + if (trailingKeep > 0) { + for (const text of contextLines.slice(-trailingKeep)) { + lines.push({ kind: "context", text }); + } + } + } + + return lines; +} + +export function schemaDiffHasChanges(lines: SchemaDiffLine[]): boolean { + return lines.some((line) => line.kind === "added" || line.kind === "removed"); +} + +function splitLines(value: string): string[] { + const lines = value.split("\n"); + + if (lines[lines.length - 1] === "") { + lines.pop(); + } + + return lines; +}