pocketbase-zod-schema 0.1.4 → 0.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/CHANGELOG.md +14 -0
- package/README.md +233 -98
- package/dist/cli/index.cjs +45 -11
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +45 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +45 -11
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +45 -11
- package/dist/cli/migrate.js.map +1 -1
- package/dist/index.cjs +86 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +81 -26
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +46 -11
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +11 -1
- package/dist/migration/analyzer.d.ts +11 -1
- package/dist/migration/analyzer.js +46 -12
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/index.cjs +45 -11
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.js +45 -11
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/mutator.cjs +20 -21
- package/dist/mutator.cjs.map +1 -1
- package/dist/mutator.d.cts +2 -2
- package/dist/mutator.d.ts +2 -2
- package/dist/mutator.js +20 -21
- package/dist/mutator.js.map +1 -1
- package/dist/schema.cjs +41 -16
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +98 -8
- package/dist/schema.d.ts +98 -8
- package/dist/schema.js +36 -15
- package/dist/schema.js.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{user-_AM523hb.d.cts → user-DTJQIj4K.d.cts} +31 -5
- package/dist/{user-_AM523hb.d.ts → user-DTJQIj4K.d.ts} +31 -5
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1](https://github.com/dastron/pocketbase-zod-schema/compare/pocketbase-zod-schema-v0.2.0...pocketbase-zod-schema-v0.2.1) (2025-12-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* remove analyzer console logs ([f632a96](https://github.com/dastron/pocketbase-zod-schema/commit/f632a96ad1d212587b712498e7061662f675bfc9))
|
|
9
|
+
|
|
10
|
+
## [0.2.0](https://github.com/dastron/pocketbase-zod-schema/compare/pocketbase-zod-schema-v0.1.4...pocketbase-zod-schema-v0.2.0) (2025-12-20)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* Add `defineCollection` to wrap schema definition ([8dbcbfa](https://github.com/dastron/pocketbase-zod-schema/commit/8dbcbfae1833509578a63e942847349cceea6cf3))
|
|
16
|
+
|
|
3
17
|
## [0.1.4](https://github.com/dastron/pocketbase-zod-schema/compare/pocketbase-zod-schema-v0.1.3...pocketbase-zod-schema-v0.1.4) (2025-12-20)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -30,31 +30,36 @@ Create a schema file in your project (e.g., `src/schema/post.ts`):
|
|
|
30
30
|
```typescript
|
|
31
31
|
import { z } from "zod";
|
|
32
32
|
import {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
defineCollection,
|
|
34
|
+
RelationField,
|
|
35
|
+
RelationsField,
|
|
36
36
|
} from "pocketbase-zod-schema/schema";
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
// Define the Zod schema
|
|
39
|
+
export const PostSchema = z.object({
|
|
40
|
+
title: z.string().min(1).max(200),
|
|
41
|
+
content: z.string(),
|
|
42
|
+
published: z.boolean().default(false),
|
|
43
|
+
|
|
44
|
+
// Single relation to users collection
|
|
45
|
+
author: RelationField({ collection: "users" }),
|
|
46
|
+
|
|
47
|
+
// Multiple relations to tags collection
|
|
48
|
+
tags: RelationsField({ collection: "tags", maxSelect: 10 }),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Define the collection with permissions
|
|
52
|
+
export const PostCollection = defineCollection({
|
|
53
|
+
collectionName: "posts",
|
|
54
|
+
schema: PostSchema,
|
|
55
|
+
permissions: {
|
|
51
56
|
listRule: '@request.auth.id != ""',
|
|
52
57
|
viewRule: "",
|
|
53
58
|
createRule: '@request.auth.id != ""',
|
|
54
59
|
updateRule: "author = @request.auth.id",
|
|
55
60
|
deleteRule: "author = @request.auth.id",
|
|
56
|
-
}
|
|
57
|
-
);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
58
63
|
```
|
|
59
64
|
|
|
60
65
|
### 2. Configure the CLI
|
|
@@ -81,10 +86,69 @@ npx pocketbase-migrate generate
|
|
|
81
86
|
|
|
82
87
|
This will create a migration file in your PocketBase migrations directory.
|
|
83
88
|
|
|
89
|
+
**TypeScript Support:** You can use TypeScript (`.ts`) schema files directly - no compilation needed! The tool automatically handles TypeScript files using `tsx`.
|
|
90
|
+
|
|
84
91
|
---
|
|
85
92
|
|
|
86
93
|
## Schema Definition
|
|
87
94
|
|
|
95
|
+
### High-Level Collection Definition
|
|
96
|
+
|
|
97
|
+
The recommended way to define collections is using `defineCollection()`, which provides a single entry point for collection name, schema, permissions, indexes, and future features:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { z } from "zod";
|
|
101
|
+
import { defineCollection, RelationField } from "pocketbase-zod-schema/schema";
|
|
102
|
+
|
|
103
|
+
export const PostCollectionSchema = z.object({
|
|
104
|
+
title: z.string(),
|
|
105
|
+
content: z.string(),
|
|
106
|
+
author: RelationField({ collection: "users" }),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
export const PostCollection = defineCollection({
|
|
110
|
+
collectionName: "posts",
|
|
111
|
+
schema: PostCollectionSchema,
|
|
112
|
+
permissions: {
|
|
113
|
+
template: "owner-only",
|
|
114
|
+
ownerField: "author",
|
|
115
|
+
},
|
|
116
|
+
indexes: [
|
|
117
|
+
"CREATE INDEX idx_posts_author ON posts (author)",
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Benefits of `defineCollection()`:**
|
|
123
|
+
- **Explicit collection name** - No need to rely on filename conventions
|
|
124
|
+
- **All metadata in one place** - Schema, permissions, indexes together
|
|
125
|
+
- **Future-proof** - Easy to extend with new features
|
|
126
|
+
- **Cleaner syntax** - No nested function calls
|
|
127
|
+
|
|
128
|
+
**Export Pattern:** It's recommended to export both the schema and collection definition:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Define the Zod schema (for type inference and validation)
|
|
132
|
+
export const PostSchema = z.object({
|
|
133
|
+
title: z.string(),
|
|
134
|
+
content: z.string(),
|
|
135
|
+
author: RelationField({ collection: "users" }),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Define the collection (used by migration generator, includes metadata)
|
|
139
|
+
export const PostCollection = defineCollection({
|
|
140
|
+
collectionName: "posts",
|
|
141
|
+
schema: PostSchema,
|
|
142
|
+
permissions: { /* ... */ },
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This pattern allows:
|
|
147
|
+
- `PostSchema` - Used for type inference (`z.infer<typeof PostSchema>`) and validation
|
|
148
|
+
- `PostCollection` - Used by the migration generator (has collection metadata)
|
|
149
|
+
|
|
150
|
+
**Note:** You can still use `withPermissions()` and `withIndexes()` separately if you prefer, but `defineCollection()` is recommended for new code.
|
|
151
|
+
|
|
88
152
|
### Field Types
|
|
89
153
|
|
|
90
154
|
The library maps Zod types to PocketBase field types automatically:
|
|
@@ -99,33 +163,33 @@ The library maps Zod types to PocketBase field types automatically:
|
|
|
99
163
|
| `z.date()` | date | `birthdate: z.date()` |
|
|
100
164
|
| `z.enum([...])` | select | `status: z.enum(["draft", "published"])` |
|
|
101
165
|
| `z.instanceof(File)` | file | `avatar: z.instanceof(File)` |
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
166
|
+
| `RelationField()` | relation | `author: RelationField({ collection: "users" })` |
|
|
167
|
+
| `RelationsField()` | relation | `tags: RelationsField({ collection: "tags" })` |
|
|
104
168
|
|
|
105
169
|
### Defining Relations
|
|
106
170
|
|
|
107
|
-
Use `
|
|
171
|
+
Use `RelationField()` for single relations and `RelationsField()` for multiple relations:
|
|
108
172
|
|
|
109
173
|
```typescript
|
|
110
|
-
import {
|
|
174
|
+
import { RelationField, RelationsField } from "pocketbase-zod-schema/schema";
|
|
111
175
|
|
|
112
176
|
const ProjectSchema = z.object({
|
|
113
177
|
name: z.string(),
|
|
114
178
|
|
|
115
179
|
// Single relation (maxSelect: 1)
|
|
116
|
-
owner:
|
|
180
|
+
owner: RelationField({ collection: "users" }),
|
|
117
181
|
|
|
118
182
|
// Single relation with cascade delete
|
|
119
|
-
category:
|
|
183
|
+
category: RelationField({
|
|
120
184
|
collection: "categories",
|
|
121
185
|
cascadeDelete: true,
|
|
122
186
|
}),
|
|
123
187
|
|
|
124
188
|
// Multiple relations (maxSelect: 999 by default)
|
|
125
|
-
collaborators:
|
|
189
|
+
collaborators: RelationsField({ collection: "users" }),
|
|
126
190
|
|
|
127
191
|
// Multiple relations with constraints
|
|
128
|
-
tags:
|
|
192
|
+
tags: RelationsField({
|
|
129
193
|
collection: "tags",
|
|
130
194
|
minSelect: 1,
|
|
131
195
|
maxSelect: 5,
|
|
@@ -135,11 +199,11 @@ const ProjectSchema = z.object({
|
|
|
135
199
|
|
|
136
200
|
#### Relation Options
|
|
137
201
|
|
|
138
|
-
**`
|
|
202
|
+
**`RelationField(config)`** - Single relation
|
|
139
203
|
- `collection: string` - Target collection name (required)
|
|
140
204
|
- `cascadeDelete?: boolean` - Delete related records when this record is deleted (default: `false`)
|
|
141
205
|
|
|
142
|
-
**`
|
|
206
|
+
**`RelationsField(config)`** - Multiple relations
|
|
143
207
|
- `collection: string` - Target collection name (required)
|
|
144
208
|
- `cascadeDelete?: boolean` - Delete related records when this record is deleted (default: `false`)
|
|
145
209
|
- `minSelect?: number` - Minimum number of relations required (default: `0`)
|
|
@@ -147,29 +211,43 @@ const ProjectSchema = z.object({
|
|
|
147
211
|
|
|
148
212
|
### Defining Permissions
|
|
149
213
|
|
|
150
|
-
Use `withPermissions()` to attach API rules to your schema:
|
|
214
|
+
Use `defineCollection()` with permissions, or `withPermissions()` to attach API rules to your schema:
|
|
151
215
|
|
|
152
216
|
```typescript
|
|
153
|
-
import { withPermissions } from "pocketbase-zod-schema/schema";
|
|
217
|
+
import { defineCollection, withPermissions } from "pocketbase-zod-schema/schema";
|
|
154
218
|
|
|
155
|
-
// Using
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
{
|
|
219
|
+
// Using defineCollection (recommended)
|
|
220
|
+
const PostCollection = defineCollection({
|
|
221
|
+
collectionName: "posts",
|
|
222
|
+
schema: z.object({ title: z.string() }),
|
|
223
|
+
permissions: {
|
|
159
224
|
listRule: '@request.auth.id != ""', // Authenticated users can list
|
|
160
225
|
viewRule: "", // Anyone can view (public)
|
|
161
226
|
createRule: '@request.auth.id != ""', // Authenticated users can create
|
|
162
227
|
updateRule: "author = @request.auth.id", // Only author can update
|
|
163
228
|
deleteRule: "author = @request.auth.id", // Only author can delete
|
|
164
|
-
}
|
|
165
|
-
);
|
|
229
|
+
},
|
|
230
|
+
});
|
|
166
231
|
|
|
167
|
-
// Using templates
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
{
|
|
232
|
+
// Using templates with defineCollection
|
|
233
|
+
const ProjectCollection = defineCollection({
|
|
234
|
+
collectionName: "projects",
|
|
235
|
+
schema: z.object({ title: z.string(), owner: RelationField({ collection: "users" }) }),
|
|
236
|
+
permissions: {
|
|
171
237
|
template: "owner-only",
|
|
172
238
|
ownerField: "owner",
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Using withPermissions (alternative approach)
|
|
243
|
+
const PostSchemaAlt = withPermissions(
|
|
244
|
+
z.object({ title: z.string() }),
|
|
245
|
+
{
|
|
246
|
+
listRule: '@request.auth.id != ""',
|
|
247
|
+
viewRule: "",
|
|
248
|
+
createRule: '@request.auth.id != ""',
|
|
249
|
+
updateRule: "author = @request.auth.id",
|
|
250
|
+
deleteRule: "author = @request.auth.id",
|
|
173
251
|
}
|
|
174
252
|
);
|
|
175
253
|
```
|
|
@@ -185,24 +263,56 @@ const ProjectSchema = withPermissions(
|
|
|
185
263
|
#### Template with Custom Overrides
|
|
186
264
|
|
|
187
265
|
```typescript
|
|
188
|
-
|
|
266
|
+
// Using defineCollection (recommended)
|
|
267
|
+
const PostCollection = defineCollection({
|
|
268
|
+
collectionName: "posts",
|
|
269
|
+
schema: z.object({ title: z.string(), author: RelationField({ collection: "users" }) }),
|
|
270
|
+
permissions: {
|
|
271
|
+
template: "owner-only",
|
|
272
|
+
ownerField: "author",
|
|
273
|
+
customRules: {
|
|
274
|
+
listRule: '@request.auth.id != ""', // Override just the list rule
|
|
275
|
+
viewRule: "", // Make viewing public
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Using withPermissions (alternative)
|
|
281
|
+
const PostSchemaAlt = withPermissions(schema, {
|
|
189
282
|
template: "owner-only",
|
|
190
283
|
ownerField: "author",
|
|
191
284
|
customRules: {
|
|
192
|
-
listRule: '@request.auth.id != ""',
|
|
193
|
-
viewRule: "",
|
|
285
|
+
listRule: '@request.auth.id != ""',
|
|
286
|
+
viewRule: "",
|
|
194
287
|
},
|
|
195
288
|
});
|
|
196
289
|
```
|
|
197
290
|
|
|
198
291
|
### Defining Indexes
|
|
199
292
|
|
|
200
|
-
Use `withIndexes()` to define database indexes:
|
|
293
|
+
Use `defineCollection()` with indexes, or `withIndexes()` to define database indexes:
|
|
201
294
|
|
|
202
295
|
```typescript
|
|
203
|
-
import { withIndexes, withPermissions } from "pocketbase-zod-schema/schema";
|
|
296
|
+
import { defineCollection, withIndexes, withPermissions } from "pocketbase-zod-schema/schema";
|
|
297
|
+
|
|
298
|
+
// Using defineCollection (recommended)
|
|
299
|
+
const UserCollection = defineCollection({
|
|
300
|
+
collectionName: "users",
|
|
301
|
+
schema: z.object({
|
|
302
|
+
email: z.string().email(),
|
|
303
|
+
username: z.string(),
|
|
304
|
+
}),
|
|
305
|
+
permissions: {
|
|
306
|
+
template: "authenticated",
|
|
307
|
+
},
|
|
308
|
+
indexes: [
|
|
309
|
+
'CREATE UNIQUE INDEX idx_users_email ON users (email)',
|
|
310
|
+
'CREATE INDEX idx_users_username ON users (username)',
|
|
311
|
+
],
|
|
312
|
+
});
|
|
204
313
|
|
|
205
|
-
|
|
314
|
+
// Using withIndexes (alternative)
|
|
315
|
+
const UserSchemaAlt = withIndexes(
|
|
206
316
|
withPermissions(
|
|
207
317
|
z.object({
|
|
208
318
|
email: z.string().email(),
|
|
@@ -310,84 +420,109 @@ Here's a complete example of a blog schema with users, posts, and comments:
|
|
|
310
420
|
```typescript
|
|
311
421
|
// src/schema/user.ts
|
|
312
422
|
import { z } from "zod";
|
|
313
|
-
import {
|
|
423
|
+
import { baseSchema, defineCollection } from "pocketbase-zod-schema/schema";
|
|
424
|
+
|
|
425
|
+
// Input schema for forms (includes passwordConfirm for validation)
|
|
426
|
+
export const UserInputSchema = z.object({
|
|
427
|
+
name: z.string().optional(),
|
|
428
|
+
email: z.string().email(),
|
|
429
|
+
password: z.string().min(8),
|
|
430
|
+
passwordConfirm: z.string(),
|
|
431
|
+
avatar: z.instanceof(File).optional(),
|
|
432
|
+
});
|
|
314
433
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
434
|
+
// Database schema (excludes passwordConfirm)
|
|
435
|
+
const UserCollectionSchema = z.object({
|
|
436
|
+
name: z.string().optional(),
|
|
437
|
+
email: z.string().email(),
|
|
438
|
+
password: z.string().min(8),
|
|
439
|
+
avatar: z.instanceof(File).optional(),
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// Full schema with base fields for type inference (includes id, collectionId, etc.)
|
|
443
|
+
export const UserSchema = UserCollectionSchema.extend(baseSchema);
|
|
444
|
+
|
|
445
|
+
// Collection definition with permissions and indexes
|
|
446
|
+
export const UserCollection = defineCollection({
|
|
447
|
+
collectionName: "Users",
|
|
448
|
+
schema: UserSchema,
|
|
449
|
+
permissions: {
|
|
450
|
+
listRule: "id = @request.auth.id",
|
|
451
|
+
viewRule: "id = @request.auth.id",
|
|
452
|
+
createRule: "",
|
|
453
|
+
updateRule: "id = @request.auth.id",
|
|
454
|
+
deleteRule: "id = @request.auth.id",
|
|
455
|
+
},
|
|
456
|
+
indexes: [
|
|
332
457
|
'CREATE UNIQUE INDEX idx_users_email ON users (email)',
|
|
333
|
-
]
|
|
334
|
-
);
|
|
458
|
+
],
|
|
459
|
+
});
|
|
335
460
|
```
|
|
336
461
|
|
|
337
462
|
```typescript
|
|
338
463
|
// src/schema/post.ts
|
|
339
464
|
import { z } from "zod";
|
|
340
465
|
import {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
466
|
+
defineCollection,
|
|
467
|
+
RelationField,
|
|
468
|
+
RelationsField,
|
|
344
469
|
} from "pocketbase-zod-schema/schema";
|
|
345
470
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
471
|
+
// Define the Zod schema
|
|
472
|
+
export const PostSchema = z.object({
|
|
473
|
+
title: z.string().min(1).max(200),
|
|
474
|
+
slug: z.string(),
|
|
475
|
+
content: z.string(),
|
|
476
|
+
excerpt: z.string().optional(),
|
|
477
|
+
published: z.boolean().default(false),
|
|
478
|
+
publishedAt: z.date().optional(),
|
|
479
|
+
|
|
480
|
+
// Relations
|
|
481
|
+
author: RelationField({ collection: "users" }),
|
|
482
|
+
category: RelationField({ collection: "categories" }),
|
|
483
|
+
tags: RelationsField({ collection: "tags", maxSelect: 10 }),
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// Define the collection with permissions
|
|
487
|
+
export const PostCollection = defineCollection({
|
|
488
|
+
collectionName: "posts",
|
|
489
|
+
schema: PostSchema,
|
|
490
|
+
permissions: {
|
|
361
491
|
listRule: 'published = true || author = @request.auth.id',
|
|
362
492
|
viewRule: 'published = true || author = @request.auth.id',
|
|
363
493
|
createRule: '@request.auth.id != ""',
|
|
364
494
|
updateRule: "author = @request.auth.id",
|
|
365
495
|
deleteRule: "author = @request.auth.id",
|
|
366
|
-
}
|
|
367
|
-
);
|
|
496
|
+
},
|
|
497
|
+
});
|
|
368
498
|
```
|
|
369
499
|
|
|
370
500
|
```typescript
|
|
371
501
|
// src/schema/comment.ts
|
|
372
502
|
import { z } from "zod";
|
|
373
|
-
import {
|
|
503
|
+
import { defineCollection, RelationField } from "pocketbase-zod-schema/schema";
|
|
374
504
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
505
|
+
// Define the Zod schema
|
|
506
|
+
export const CommentSchema = z.object({
|
|
507
|
+
content: z.string().min(1),
|
|
508
|
+
|
|
509
|
+
// Relations with cascade delete
|
|
510
|
+
post: RelationField({ collection: "posts", cascadeDelete: true }),
|
|
511
|
+
author: RelationField({ collection: "users" }),
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// Define the collection with permissions
|
|
515
|
+
export const CommentCollection = defineCollection({
|
|
516
|
+
collectionName: "comments",
|
|
517
|
+
schema: CommentSchema,
|
|
518
|
+
permissions: {
|
|
384
519
|
listRule: "",
|
|
385
520
|
viewRule: "",
|
|
386
521
|
createRule: '@request.auth.id != ""',
|
|
387
522
|
updateRule: "author = @request.auth.id",
|
|
388
523
|
deleteRule: "author = @request.auth.id || @request.auth.role = 'admin'",
|
|
389
|
-
}
|
|
390
|
-
);
|
|
524
|
+
},
|
|
525
|
+
});
|
|
391
526
|
```
|
|
392
527
|
|
|
393
528
|
---
|
package/dist/cli/index.cjs
CHANGED
|
@@ -1076,6 +1076,16 @@ function isFieldRequired(zodType) {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
1078
|
// src/migration/analyzer.ts
|
|
1079
|
+
var tsxLoaderRegistered = false;
|
|
1080
|
+
async function ensureTsxLoader() {
|
|
1081
|
+
if (tsxLoaderRegistered) return;
|
|
1082
|
+
try {
|
|
1083
|
+
await import('tsx/esm');
|
|
1084
|
+
tsxLoaderRegistered = true;
|
|
1085
|
+
} catch {
|
|
1086
|
+
tsxLoaderRegistered = false;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1079
1089
|
var DEFAULT_CONFIG = {
|
|
1080
1090
|
workspaceRoot: process.cwd(),
|
|
1081
1091
|
excludePatterns: [
|
|
@@ -1173,24 +1183,37 @@ async function importSchemaModule(filePath, config) {
|
|
|
1173
1183
|
} else {
|
|
1174
1184
|
resolvedPath = jsPath;
|
|
1175
1185
|
}
|
|
1186
|
+
if (resolvedPath.endsWith(".ts")) {
|
|
1187
|
+
await ensureTsxLoader();
|
|
1188
|
+
if (!tsxLoaderRegistered) {
|
|
1189
|
+
throw new SchemaParsingError(
|
|
1190
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
1191
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
1192
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
1193
|
+
filePath
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1176
1197
|
const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
|
|
1177
1198
|
const module = await import(fileUrl.href);
|
|
1178
1199
|
return module;
|
|
1179
1200
|
} catch (error) {
|
|
1180
1201
|
const tsPath = `${filePath}.ts`;
|
|
1181
1202
|
const isTypeScriptFile = fs5__namespace.existsSync(tsPath);
|
|
1203
|
+
if (isTypeScriptFile && error instanceof SchemaParsingError) {
|
|
1204
|
+
throw error;
|
|
1205
|
+
}
|
|
1182
1206
|
if (isTypeScriptFile) {
|
|
1183
1207
|
throw new SchemaParsingError(
|
|
1184
|
-
`Failed to import TypeScript schema file.
|
|
1185
|
-
Please
|
|
1186
|
-
|
|
1187
|
-
2. Use tsx to run the migration tool (e.g., "npx tsx package/dist/cli/migrate.js status" or "tsx package/dist/cli/migrate.js status")`,
|
|
1208
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
1209
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
1210
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
1188
1211
|
filePath,
|
|
1189
1212
|
error
|
|
1190
1213
|
);
|
|
1191
1214
|
}
|
|
1192
1215
|
throw new SchemaParsingError(
|
|
1193
|
-
`Failed to import schema module. Make sure the schema files
|
|
1216
|
+
`Failed to import schema module. Make sure the schema files exist and are valid.`,
|
|
1194
1217
|
filePath,
|
|
1195
1218
|
error
|
|
1196
1219
|
);
|
|
@@ -1200,6 +1223,19 @@ function getCollectionNameFromFile(filePath) {
|
|
|
1200
1223
|
const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1201
1224
|
return toCollectionName(filename);
|
|
1202
1225
|
}
|
|
1226
|
+
function extractCollectionNameFromSchema(zodSchema) {
|
|
1227
|
+
if (!zodSchema.description) {
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
try {
|
|
1231
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1232
|
+
if (metadata.collectionName && typeof metadata.collectionName === "string") {
|
|
1233
|
+
return metadata.collectionName;
|
|
1234
|
+
}
|
|
1235
|
+
} catch {
|
|
1236
|
+
}
|
|
1237
|
+
return null;
|
|
1238
|
+
}
|
|
1203
1239
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
|
|
1204
1240
|
const result = {};
|
|
1205
1241
|
for (const [key, value] of Object.entries(module)) {
|
|
@@ -1274,11 +1310,8 @@ function buildFieldDefinition(fieldName, zodType) {
|
|
|
1274
1310
|
// Default to false, can be configured later
|
|
1275
1311
|
};
|
|
1276
1312
|
if (fieldDef.options) {
|
|
1277
|
-
const { min, max, pattern, ...relationSafeOptions } = fieldDef.options;
|
|
1278
|
-
|
|
1279
|
-
console.log("max", max);
|
|
1280
|
-
console.log("pattern", pattern);
|
|
1281
|
-
fieldDef.options = Object.keys(relationSafeOptions).length > 0 ? relationSafeOptions : void 0;
|
|
1313
|
+
const { min: _min, max: _max, pattern: _pattern, ...relationSafeOptions } = fieldDef.options;
|
|
1314
|
+
fieldDef.options = Object.keys(relationSafeOptions).length ? relationSafeOptions : void 0;
|
|
1282
1315
|
}
|
|
1283
1316
|
}
|
|
1284
1317
|
return fieldDef;
|
|
@@ -1375,7 +1408,8 @@ async function buildSchemaDefinition(config) {
|
|
|
1375
1408
|
console.warn(`No valid schema found in ${filePath}, skipping...`);
|
|
1376
1409
|
continue;
|
|
1377
1410
|
}
|
|
1378
|
-
const
|
|
1411
|
+
const collectionNameFromSchema = extractCollectionNameFromSchema(zodSchema);
|
|
1412
|
+
const collectionName = collectionNameFromSchema ?? getCollectionNameFromFile(filePath);
|
|
1379
1413
|
const collectionSchema = convertZodSchemaToCollectionSchema(collectionName, zodSchema);
|
|
1380
1414
|
collections.set(collectionName, collectionSchema);
|
|
1381
1415
|
} catch (error) {
|