@prismakit/cli 3.1.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prismakit/cli",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "CLI for PrismaKit — generate modules, validate compose, install agent skills",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -28,11 +28,18 @@
|
|
|
28
28
|
"LICENSE",
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
35
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
36
|
+
"clean": "rm -rf dist"
|
|
37
|
+
},
|
|
31
38
|
"dependencies": {
|
|
32
|
-
"@prismakit/core": "
|
|
39
|
+
"@prismakit/core": "workspace:*"
|
|
33
40
|
},
|
|
34
41
|
"peerDependencies": {
|
|
35
|
-
"@prismakit/core": ">=3.
|
|
42
|
+
"@prismakit/core": ">=3.2.0 <4"
|
|
36
43
|
},
|
|
37
44
|
"devDependencies": {
|
|
38
45
|
"typescript": "^5.9.2",
|
|
@@ -56,12 +63,5 @@
|
|
|
56
63
|
"prismakit",
|
|
57
64
|
"cursor",
|
|
58
65
|
"skills"
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
"build": "tsup",
|
|
62
|
-
"test": "vitest run",
|
|
63
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
64
|
-
"lint": "tsc -p tsconfig.json --noEmit",
|
|
65
|
-
"clean": "rm -rf dist"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -52,8 +52,9 @@ Helpers may inject repositories — never the Prisma client.
|
|
|
52
52
|
| Existence / uniqueness / auth | `getFirst` — **no** `setCache` |
|
|
53
53
|
| List | `getMany` + `setCache: true` + optional `cacheTags` |
|
|
54
54
|
| Paginated list | `getManyPaginate` |
|
|
55
|
-
| Large / infinite list | `getManyCursor` |
|
|
55
|
+
| Large / infinite list | `getManyCursor` (with `cursor` → default `skip: 1`) |
|
|
56
56
|
| Count / exists check | `count` / `exists` (no `setCache` on auth paths) |
|
|
57
|
+
| Composite PK row | `id: { a, b }` object — kit maps to Prisma `a_b: { a, b }` |
|
|
57
58
|
| Aggregations | `aggregate` / `groupBy` |
|
|
58
59
|
| Create / update / delete | matching mutation; default invalidation is enough outside tx |
|
|
59
60
|
| Multi-step write | one transaction; pass `tx` into every repo call |
|
|
@@ -63,7 +64,7 @@ Helpers may inject repositories — never the Prisma client.
|
|
|
63
64
|
## Create a repository (core)
|
|
64
65
|
|
|
65
66
|
```typescript
|
|
66
|
-
import {
|
|
67
|
+
import { PrismaClient } from '@prisma/client';
|
|
67
68
|
import { createRepository } from '@prismakit/core';
|
|
68
69
|
import { RedisCacheAdapter } from '@prismakit/redis';
|
|
69
70
|
|
|
@@ -71,9 +72,8 @@ const DAY = 86_400;
|
|
|
71
72
|
|
|
72
73
|
const UserRepoClass = createRepository({
|
|
73
74
|
model: 'user',
|
|
74
|
-
scalarFields: Prisma.UserScalarFieldEnum,
|
|
75
75
|
cache: { ttl: DAY, nullTtl: 60, sensitiveFields: ['password'] },
|
|
76
|
-
lock: true, // table + columns from Prisma meta
|
|
76
|
+
lock: true, // table + columns resolved from Prisma schema meta
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
const prisma = new PrismaClient();
|
|
@@ -83,14 +83,16 @@ export const users = new UserRepoClass({ prisma, cache });
|
|
|
83
83
|
|
|
84
84
|
`defineRepository` and `createPrismaRepository` are aliases of `createRepository`.
|
|
85
85
|
|
|
86
|
+
**NestJS apps:** use `createDefineRepo` / `defineAppRepo` with app-wide cache defaults instead — see skill `prismakit-nestjs`.
|
|
87
|
+
|
|
86
88
|
| Option | Description |
|
|
87
89
|
|--------|-------------|
|
|
88
90
|
| `model` | Prisma client key (`prisma.user` → `'user'`). Needed for cache + compose. |
|
|
89
|
-
| `scalarFields` | Usually `Prisma.XScalarFieldEnum`.
|
|
90
|
-
| `cache` | `CacheOptions` or `true`
|
|
91
|
+
| `scalarFields` | Usually `Prisma.XScalarFieldEnum`. **Optional** when `schemaPath` / DMMF meta is loaded (default since 3.1). |
|
|
92
|
+
| `cache` | `CacheOptions` or `true` (uses app defaults when bound via `createDefineRepo`). |
|
|
91
93
|
| `lock` | `true` / client key / `@@map` table / `{ tableName, columns }`. |
|
|
92
94
|
| `primaryKey` | Override only. Defaults to schema `@id` / `@@id` (composite `string[]`) or `id`. |
|
|
93
|
-
| `schemaPath` | Path to `schema.prisma` when meta is not loaded globally. |
|
|
95
|
+
| `schemaPath` | Path to `schema.prisma` when meta is not loaded globally. Default: `prisma/schema.prisma`. |
|
|
94
96
|
| `getDelegate` | Optional. Defaults to `(c) => c[model]`. |
|
|
95
97
|
|
|
96
98
|
Put files under `**/repositories/**`. Keep Prisma client construction under `**/infrastructure/prisma/**`.
|
|
@@ -124,7 +126,9 @@ await users.getFirst({
|
|
|
124
126
|
| `count` / `exists` | `{ count }` / `{ exists }` |
|
|
125
127
|
| `aggregate` / `groupBy` | Prisma delegate results |
|
|
126
128
|
|
|
127
|
-
`id` is `string` or `Record<string, string>` for composite PKs.
|
|
129
|
+
`id` is `string` or `Record<string, string>` for composite PKs (object form for `@@id([a,b])`).
|
|
130
|
+
|
|
131
|
+
`getManyCursor`: when `cursor` is set, default `skip` is `1` so the cursor row is not repeated. Pass `skip: 0` only for inclusive semantics.
|
|
128
132
|
|
|
129
133
|
## Writes
|
|
130
134
|
|
|
@@ -234,6 +238,11 @@ export default [prismakit.configs.recommended];
|
|
|
234
238
|
|
|
235
239
|
Allowed Prisma usage: `**/repositories/**`, `**/infrastructure/prisma/**`. Rules: `no-prisma-service-outside-repos`, `no-direct-prisma-delegate`, `require-transaction-service`, `require-cached-repo-provider`.
|
|
236
240
|
|
|
241
|
+
## Observability
|
|
242
|
+
|
|
243
|
+
- Core: `setTelemetry({ enabled, onEvent })` or Nest `telemetry` / `queryLog.slowThreshold`.
|
|
244
|
+
- Optional: `@prismakit/opentelemetry` → `createPrismaKitTelemetry({ slowThreshold })`.
|
|
245
|
+
|
|
237
246
|
## Clean code
|
|
238
247
|
|
|
239
248
|
- One repository per Prisma model, file `*.repository.ts` under `repositories/`.
|
|
@@ -241,6 +250,7 @@ Allowed Prisma usage: `**/repositories/**`, `**/infrastructure/prisma/**`. Rules
|
|
|
241
250
|
- Named TTL constants (`const DAY = 86_400`), not magic numbers scattered in call sites.
|
|
242
251
|
- Pass `tx` into **every** repo call in a unit of work. Do not mix cached reads with half-committed writes.
|
|
243
252
|
- Tests: `@prismakit/memory` `MemoryCacheAdapter`. Production: `@prismakit/redis`.
|
|
253
|
+
- Library CI proves PG+Redis paths under `FORCE_INTEGRATION=1` (CRUD, compose, locks, stampede, fail-open).
|
|
244
254
|
|
|
245
255
|
## Anti-patterns (BAD → GOOD)
|
|
246
256
|
|
|
@@ -9,16 +9,18 @@ API surface for `@prismakit/core` 3.x. Read [SKILL.md](SKILL.md) first.
|
|
|
9
9
|
| `@prismakit/core` | `createRepository`, AutoComposer, locks, pagination, `CacheAdapter` |
|
|
10
10
|
| `@prismakit/redis` | `RedisCacheAdapter` |
|
|
11
11
|
| `@prismakit/memory` | `MemoryCacheAdapter` (tests / local) |
|
|
12
|
+
| `@prismakit/opentelemetry` | Map telemetry → OTel metrics/spans |
|
|
12
13
|
| `@prismakit/cli` | `prismakit generate / validate / skills` |
|
|
13
14
|
| `@prismakit/eslint-plugin` | Repository-only data-access rules |
|
|
14
15
|
|
|
15
|
-
Node ≥ 20. Install:
|
|
16
|
+
Node ≥ 20. Line **3.2.x**. Install:
|
|
16
17
|
|
|
17
18
|
```bash
|
|
18
19
|
pnpm add @prismakit/core
|
|
19
20
|
pnpm add @prismakit/redis ioredis # optional production cache
|
|
20
21
|
pnpm add -D @prismakit/eslint-plugin @prismakit/cli
|
|
21
22
|
# tests: pnpm add -D @prismakit/memory
|
|
23
|
+
# optional: pnpm add @prismakit/opentelemetry @opentelemetry/api
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
## Factory
|
|
@@ -40,7 +42,7 @@ Aliases: `defineRepository`, `createPrismaRepository`.
|
|
|
40
42
|
| `cache` | `CacheOptions \| true` | `true` → `{ ttl: 86400, sensitiveFields: ['password'] }`. |
|
|
41
43
|
| `lock` | `true \| string \| RepositoryLockConfig` | `true` / client key / Pascal name / `@@map` table. |
|
|
42
44
|
| `schemaPath` | `string` | Lock/schema helpers when global meta is missing. |
|
|
43
|
-
| `primaryKey` | `string \| string[]` | `*ById` + row locks. Default: meta PK or `id`. |
|
|
45
|
+
| `primaryKey` | `string \| string[]` | `*ById` + row locks. Default: meta PK or `id`. Composite → Prisma `a_b: { a, b }` where. |
|
|
44
46
|
| `getDelegate` | `(client) => delegate` | Default `(c) => c[model]`. |
|
|
45
47
|
| `toPayload` | `(data) => payload` | Default identity. Prefer typed factories over this. |
|
|
46
48
|
|
|
@@ -59,7 +61,7 @@ All methods accept optional `tx`. Cached repos also accept cache fields (see bel
|
|
|
59
61
|
| `getFirst` | `where?`, `select?`, `lock?`, `setCache?`, `cacheTags?` | `T \| null` |
|
|
60
62
|
| `getMany` | `where?`, `select?`, `orderBy?`, `take?`, `skip?`, `lock?`, `setCache?`, `cacheTags?` | `T[]` |
|
|
61
63
|
| `getManyPaginate` | `where?`, `select?`, `orderBy?`, `page?`, `pageSize?`, `setCache?`, `cacheTags?` | `PaginatedResult<T>` |
|
|
62
|
-
| `getManyCursor` | `where?`, `select?`, `orderBy?`, `cursor?`, `take?`, `skip?`, `setCache?`, `cacheTags?` | `CursorPage<T
|
|
64
|
+
| `getManyCursor` | `where?`, `select?`, `orderBy?`, `cursor?`, `take?`, `skip?`, `setCache?`, `cacheTags?` | `CursorPage<T>`; with `cursor`, default `skip: 1` |
|
|
63
65
|
| `count` | `where?`, `select?`, `setCache?`, `cacheTags?` | `{ count: number }` |
|
|
64
66
|
| `exists` | `where?`, `setCache?`, `cacheTags?` | `{ exists: boolean }` |
|
|
65
67
|
| `aggregate` | Prisma aggregate args + `setCache?`, `cacheTags?` | delegate result |
|
|
@@ -45,37 +45,65 @@ export class AppModule {}
|
|
|
45
45
|
|
|
46
46
|
## Factory (one default)
|
|
47
47
|
|
|
48
|
-
Bind `Prisma.TypeMap` once, then define repos with
|
|
48
|
+
Bind `Prisma.TypeMap` once with app-wide cache defaults, then define repos with per-model overrides only.
|
|
49
49
|
|
|
50
50
|
```typescript
|
|
51
|
-
// src/infrastructure/prisma/define-repo.ts
|
|
51
|
+
// src/infrastructure/prisma/define-app-repo.ts
|
|
52
52
|
import { createDefineRepo } from '@prismakit/nestjs';
|
|
53
|
-
import type { Prisma } from '@prisma/client';
|
|
53
|
+
import type { Prisma } from '@prisma/client'; // or generated client path
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
const DAY = 86_400;
|
|
56
|
+
|
|
57
|
+
export const defineAppRepo = createDefineRepo<Prisma.TypeMap>({
|
|
58
|
+
cache: {
|
|
59
|
+
ttl: DAY,
|
|
60
|
+
nullTtl: 60,
|
|
61
|
+
defaultSetCache: true,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
56
64
|
```
|
|
57
65
|
|
|
58
66
|
```typescript
|
|
59
67
|
// src/modules/users/repositories/user.repository.ts
|
|
60
|
-
import {
|
|
61
|
-
import { defineRepo } from '../../../infrastructure/prisma/define-repo';
|
|
62
|
-
|
|
63
|
-
const DAY = 86_400;
|
|
68
|
+
import { defineAppRepo } from 'src/infrastructure/prisma/define-app-repo';
|
|
64
69
|
|
|
65
|
-
export class UserRepository extends
|
|
70
|
+
export class UserRepository extends defineAppRepo({
|
|
66
71
|
model: 'user',
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
cache: {
|
|
73
|
+
defaultSetCache: false, // auth lookups pass setCache explicitly
|
|
74
|
+
sensitiveFields: ['password'],
|
|
75
|
+
methods: { getFirst: { enabled: false } },
|
|
76
|
+
},
|
|
70
77
|
}) {}
|
|
71
78
|
```
|
|
72
79
|
|
|
80
|
+
```typescript
|
|
81
|
+
// src/modules/category/repositories/category.repository.ts
|
|
82
|
+
import { defineAppRepo } from 'src/infrastructure/prisma/define-app-repo';
|
|
83
|
+
|
|
84
|
+
export class CategoryRepository extends defineAppRepo({
|
|
85
|
+
model: 'category',
|
|
86
|
+
cache: true, // inherits app-wide defaults (ttl, nullTtl, defaultSetCache)
|
|
87
|
+
}) {}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Uncached repo — TypeScript omits setCache / invalidateCache
|
|
92
|
+
import { defineAppRepo } from 'src/infrastructure/prisma/define-app-repo';
|
|
93
|
+
|
|
94
|
+
export class AuditLogRepository extends defineAppRepo({
|
|
95
|
+
model: 'auditLog',
|
|
96
|
+
}) {}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`scalarFields` is **optional** when `schemaPath` or DMMF meta is loaded (default since 3.1). Omit it in new repos.
|
|
100
|
+
|
|
73
101
|
Escape hatches (do not use as the app default):
|
|
74
102
|
|
|
75
103
|
- `defineInjectableRepository` from `@prismakit/nestjs` (package alias `defineRepository`) — phantoms + payload HKT when TypeMap is unavailable.
|
|
76
104
|
- `createInjectableRepository` without a types bag — thin, results are `unknown`. Alias: `createPrismaRepository`.
|
|
77
105
|
|
|
78
|
-
Do not import `defineRepo` from `@prismakit/nestjs` in apps that already bind `createDefineRepo` as `
|
|
106
|
+
Do not import `defineRepo` from `@prismakit/nestjs` in apps that already bind `createDefineRepo` as `defineAppRepo`.
|
|
79
107
|
|
|
80
108
|
## Register and inject
|
|
81
109
|
|
|
@@ -196,8 +224,8 @@ Repository `cache` is the source of truth. Omit `cacheModels` (fail-open). Pass
|
|
|
196
224
|
| `validateCompose: true` | Assert compose-safe selects on boot |
|
|
197
225
|
| `strictCachedRepos` | Fail boot if a `cache` repo class is not in Nest `providers` (default `true`) |
|
|
198
226
|
| `compose` | `{ maxDepth, parallel, setCache }` |
|
|
199
|
-
| `telemetry` | `{ enabled: true, onEvent }` |
|
|
200
|
-
| `queryLog` | `{ slowThreshold, onSlowQuery }` — enables telemetry |
|
|
227
|
+
| `telemetry` | `{ enabled: true, onEvent }` or `createPrismaKitTelemetry()` from `@prismakit/opentelemetry` |
|
|
228
|
+
| `queryLog` | `{ slowThreshold, onSlowQuery }` — enables telemetry / `query.slow` |
|
|
201
229
|
| `autoRegisterModels` | `true` or `string[]` — stub repos for compose-only models |
|
|
202
230
|
|
|
203
231
|
## Scaffolding
|
|
@@ -205,12 +233,15 @@ Repository `cache` is the source of truth. Omit `cacheModels` (fail-open). Pass
|
|
|
205
233
|
```bash
|
|
206
234
|
npx prismakit generate product --cache
|
|
207
235
|
npx prismakit generate product --cache --full --route products
|
|
236
|
+
npx prismakit skills # refresh .cursor/skills after upgrades
|
|
208
237
|
```
|
|
209
238
|
|
|
210
239
|
Repo-only: add the class to feature `providers`. `--full`: import `*Module` in `AppModule`. Then `npx prismakit validate`.
|
|
211
240
|
|
|
212
241
|
Enable ESLint `prismakit.configs.recommended` (see skill `prismakit`).
|
|
213
242
|
|
|
243
|
+
Reference app: [starter-prismakit-nestjs](https://github.com/fikiap23/starter-prismakit-nestjs) (Nest 11 + Prisma 7 + Redis).
|
|
244
|
+
|
|
214
245
|
## Clean code (Nest)
|
|
215
246
|
|
|
216
247
|
- One `defineRepo` binder under `src/infrastructure/prisma/`. Do not call `createDefineRepo` per feature.
|