@suss/contract-prisma 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +84 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @suss/contract-prisma
2
+
3
+ Generate suss `BehavioralSummary[]` from a [Prisma](https://www.prisma.io/) schema. A `schema.prisma` file declares every table an application has and every column on it, which is the contract the code reads and writes against. This reader turns that declaration into storage boundaries, so a query touching a column nobody declared becomes a finding.
4
+
5
+ ## What this package reads
6
+
7
+ `@suss/contract-prisma` parses `schema.prisma` with [`@mrleebo/prisma-ast`](https://github.com/MrLeebo/prisma-ast), a parser that does not pull in the Prisma runtime, so reading a schema never requires a generated client or a database connection.
8
+
9
+ The `datasource` block decides whether anything comes out. A `provider` of `postgresql`, `postgres`, `mysql`, or `sqlite` sets the storage system on every boundary. Any other provider (MongoDB, for instance) returns an empty array, since document semantics are a different boundary kind.
10
+
11
+ ## What it produces
12
+
13
+ One `library`-kind summary per `model` and per `view`, with a storage boundary binding: `recognition: "prisma"`, the storage system from the datasource, a scope, and the model name as the container. The checker's storage pass pairs those against `interaction(class: "storage-access")` effects the adapters find in code. A monorepo with several Prisma schemas should pass a distinct `scope` per schema so pairings stay separate; it defaults to `"default"`.
14
+
15
+ The behavior is in `metadata.storageContract`:
16
+
17
+ - `fieldSet: "exhaustive"`. A Prisma model declares every column its table has, so a column the code touches and this list leaves out is unknown rather than merely unlisted.
18
+ - `fields`, one entry per column, with the Prisma type, whether the field is optional (`nullable`), and `primary` / `unique` from the `@id` and `@unique` field attributes. Scalar fields (`Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean`, `DateTime`, `Json`, `Bytes`) and enum fields are columns.
19
+ - Relation fields also appear, marked `derived`, because the Prisma client accepts them in an `include` or a `select` even though no column of that name exists. Leaving them out of a contract that calls itself exhaustive would report working code as reading an undeclared field. When the model stores the foreign key, the columns listed in `@relation(fields: [...])` come along as `relationKey`. Prisma allows that argument on one side of a relation only, so the other side and every implicit many-to-many have no key: connecting a row there changes a join-table entry rather than a column of this model.
20
+ - A model with any relation also gets a derived `_count` entry, which is what the client exposes for relation counts.
21
+ - `indexes`, from `@@index([...])` (not unique), `@@unique([...])`, and `@@id([...])` (both unique).
22
+ - `physicalTable`, when `@@map("...")` gives the table a SQL name different from the model name. That is the bridge to code speaking SQL names directly, such as Drizzle's `pgTable("users")` or a raw query.
23
+
24
+ These summaries have no inputs and no transitions. A table is a shape the code agrees with, not a function that returns something. Confidence is `declared` at `high`, since the schema says all of this outright.
25
+
26
+ ## What it does not read
27
+
28
+ - **Non-relational providers.** A MongoDB schema comes back empty; document storage semantics are separate work.
29
+ - **Composite types and unsupported field types.** A field whose type is neither a scalar, an enum, nor another model (`Unsupported(...)`, a Mongo composite type, or a typo) is skipped rather than guessed at.
30
+ - **Array scalar fields.** `String[]` is dropped along with relation lists, because the walk treats every array field as a relation array.
31
+ - **Native type attributes.** `@db.VarChar(255)` and friends are not recorded; the field's Prisma type is what comes through.
32
+ - **`generator` blocks, the datasource URL, and relation cardinality** as behavior of their own.
33
+
34
+ ## Worked example
35
+
36
+ ```prisma
37
+ datasource db {
38
+ provider = "postgresql"
39
+ url = env("DATABASE_URL")
40
+ }
41
+
42
+ model User {
43
+ id Int @id @default(autoincrement())
44
+ email String @unique
45
+ name String?
46
+ posts Post[]
47
+
48
+ @@map("users")
49
+ @@index([email])
50
+ }
51
+ ```
52
+
53
+ ```sh
54
+ suss contract --from prisma prisma/schema.prisma -o summaries/db.json
55
+ suss check summaries/db.json summaries/app.json
56
+ ```
57
+
58
+ The `User` summary declares `id` (primary), `email` (unique), a nullable `name`, the derived `posts` relation, a derived `_count`, an index on `email`, and `physicalTable: "users"`.
59
+
60
+ Or programmatically:
61
+
62
+ ```ts
63
+ import { prismaSchemaFileToSummaries } from "@suss/contract-prisma";
64
+
65
+ const summaries = prismaSchemaFileToSummaries("prisma/schema.prisma", {
66
+ scope: "billing",
67
+ });
68
+ ```
69
+
70
+ ## Where it fits in suss
71
+
72
+ Depends only on `@suss/behavioral-ir` (for the IR types it produces) and `@mrleebo/prisma-ast` (for parsing). It does not extract from source code and is independent of the language adapters. The Prisma pattern pack is what finds the query call sites this contract pairs against.
73
+
74
+ ## Coverage
75
+
76
+ ![coverage](../../../.github/badges/coverage-contract-prisma.svg)
77
+
78
+ ## License
79
+
80
+ Licensed under Apache 2.0. See [LICENSE](../../../LICENSE).
81
+
82
+ ---
83
+
84
+ For the format the summaries conform to, see [`docs/behavioral-summary-format.md`](../../../docs/behavioral-summary-format.md). For how contract sources fit together, see [`docs/contract-sources.md`](../../../docs/contract-sources.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/contract-prisma",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "description": "Generate suss behavioral summaries from Prisma schema declarations.",
6
6
  "keywords": [
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@mrleebo/prisma-ast": "^0.15.0",
50
- "@suss/behavioral-ir": "0.20.0"
50
+ "@suss/behavioral-ir": "0.21.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "tsup": "*",