pocketbase-to-zod 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # pocketbase-to-zod
2
+
3
+ A lightweight CLI tool to automatically generate **Zod schemas** and **TypeScript types** directly from your **PocketBase** collections.
4
+
5
+ ## Features
6
+ * ⚡ **Real-time Generation**: Connects to your PocketBase instance via URL.
7
+ * 🛡️ **Type Safety**: Generates both Zod schemas for runtime validation and TS types for compile-time safety.
8
+ * 🔄 **Smart Mapping**: Automatically maps PocketBase field types (Select, Relation, File, Date, etc.) to the appropriate Zod logic.
9
+ * 📦 **Fullstack Ready**: Perfect for sharing schemas between your backend (Nitro/Node) and your frontend.
10
+ * 🏎️ **Lightweight & Fast**: Minimal dependencies for quick setup and execution.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install -g pocketbase-to-zod
16
+ # or use it via npx
17
+ npx pocketbase-to-zod [options]
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```bash
23
+ pocketbase-to-zod --url http://localhost:8090 --email admin@example.com --password yourpassword --output ./schemas.ts
24
+ ```
25
+
26
+ ## Options
27
+ - `--url <url>`: PocketBase instance URL (default: `http://localhost:8090`) [Required]
28
+ - `--email <email>`: Admin email for authentication [Required]
29
+ - `--password <password>`: Admin password for authentication [Required]
30
+ - `--output <file>`: Output file path for generated schemas (default: `./pocketbase-schemas.ts`) [Optional]
31
+
32
+ ## Example Output
33
+
34
+ ```typescript
35
+ import { z } from "zod";
36
+
37
+ export const UserSchema = z.object({
38
+ id: z.string(),
39
+ created: z.string().refine((date) => !isNaN(Date.parse(date)), {
40
+ message: "Invalid date format",
41
+ }),
42
+ updated: z.string().refine((date) => !isNaN(Date.parse(date)), {
43
+ message: "Invalid date format",
44
+ }),
45
+ email: z.string().email(),
46
+ verified: z.boolean(),
47
+ username: z.string().min(3).max(50),
48
+ // ... other fields
49
+ });
50
+
51
+ export type User = z.infer<typeof UserSchema>;
52
+ ```
53
+
54
+ ## Contributing
55
+ Contributions are welcome! Please open an issue or submit a pull request on GitHub.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const pocketbase_1 = __importDefault(require("pocketbase"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const program = new commander_1.Command();
12
+ program
13
+ .name('pocketbase-to-zod')
14
+ .description('Generate Zod schemas from a PocketBase instance')
15
+ .requiredOption('-u, --url <char>', 'PocketBase URL')
16
+ .requiredOption('-e, --email <char>', 'Admin email')
17
+ .requiredOption('-p, --password <char>', 'Admin password')
18
+ .option('-o, --output <char>', 'Output file path', './pocketbase-schema.ts')
19
+ .action(async (options) => {
20
+ const pb = new pocketbase_1.default(options.url);
21
+ try {
22
+ console.log('--- Authenticating with PocketBase ---');
23
+ await pb.collection('_superusers').authWithPassword(options.email, options.password);
24
+ console.log('--- Fetching collections ---');
25
+ const collections = await pb.collections.getFullList();
26
+ let fileContent = `import { z } from 'zod';\n\n`;
27
+ for (const col of collections) {
28
+ fileContent += `// Schema for collection: ${col.name}\n`;
29
+ fileContent += `export const ${col.name}Schema = z.object({\n`;
30
+ // Base PocketBase fields
31
+ fileContent += ` id: z.string(),\n`;
32
+ fileContent += ` created: z.string(),\n`;
33
+ fileContent += ` updated: z.string(),\n`;
34
+ for (const field of col.schema) {
35
+ let zodType = 'z.any()';
36
+ switch (field.type) {
37
+ case 'text':
38
+ case 'editor':
39
+ case 'url':
40
+ case 'email':
41
+ zodType = 'z.string()';
42
+ break;
43
+ case 'number':
44
+ zodType = 'z.number()';
45
+ break;
46
+ case 'bool':
47
+ zodType = 'z.boolean()';
48
+ break;
49
+ case 'date':
50
+ zodType = 'z.string().datetime()'; // PocketBase sends dates as ISO strings
51
+ break;
52
+ case 'select':
53
+ if (field.options.values) {
54
+ const values = field.options.values.map((v) => `'${v}'`).join(', ');
55
+ zodType = `z.enum([${values}])`;
56
+ }
57
+ break;
58
+ case 'relation':
59
+ zodType = field.options.maxSelect === 1 ? 'z.string()' : 'z.array(z.string())';
60
+ break;
61
+ case 'file':
62
+ zodType = field.options.maxSelect === 1 ? 'z.string()' : 'z.array(z.string())';
63
+ break;
64
+ case 'json':
65
+ zodType = 'z.unknown()';
66
+ break;
67
+ }
68
+ if (!field.required) {
69
+ zodType += '.optional().nullable()';
70
+ }
71
+ fileContent += ` ${field.name}: ${zodType},\n`;
72
+ }
73
+ fileContent += `});\n\n`;
74
+ fileContent += `export type ${col.name.charAt(0).toUpperCase() + col.name.slice(1)} = z.infer<typeof ${col.name}Schema>;\n\n`;
75
+ }
76
+ const outputPath = path_1.default.resolve(process.cwd(), options.output);
77
+ fs_1.default.writeFileSync(outputPath, fileContent);
78
+ console.log(`✅ Schemas generated successfully at: ${outputPath}`);
79
+ }
80
+ catch (error) {
81
+ console.error('❌ Error:', error.message);
82
+ process.exit(1);
83
+ }
84
+ });
85
+ program.parse();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/index.ts ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import PocketBase from 'pocketbase';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name('pocketbase-to-zod')
12
+ .description('Generate Zod schemas from a PocketBase instance')
13
+ .requiredOption('-u, --url <char>', 'PocketBase URL')
14
+ .requiredOption('-e, --email <char>', 'Admin email')
15
+ .requiredOption('-p, --password <char>', 'Admin password')
16
+ .option('-o, --output <char>', 'Output file path', './pocketbase-schema.ts')
17
+ .action(async (options) => {
18
+ const pb = new PocketBase(options.url);
19
+
20
+ try {
21
+ console.log('--- Authenticating with PocketBase ---');
22
+ await pb.collection('_superusers').authWithPassword(options.email, options.password);
23
+
24
+ console.log('--- Fetching collections ---');
25
+ const collections = await pb.collections.getFullList();
26
+
27
+ let fileContent = `import { z } from 'zod';\n\n`;
28
+
29
+ for (const col of collections) {
30
+ fileContent += `// Schema for collection: ${col.name}\n`;
31
+ fileContent += `export const ${col.name}Schema = z.object({\n`;
32
+
33
+ // Base PocketBase fields
34
+ fileContent += ` id: z.string(),\n`;
35
+ fileContent += ` created: z.string(),\n`;
36
+ fileContent += ` updated: z.string(),\n`;
37
+
38
+ for (const field of col.schema) {
39
+ let zodType = 'z.any()';
40
+
41
+ switch (field.type) {
42
+ case 'text':
43
+ case 'editor':
44
+ case 'url':
45
+ case 'email':
46
+ zodType = 'z.string()';
47
+ break;
48
+ case 'number':
49
+ zodType = 'z.number()';
50
+ break;
51
+ case 'bool':
52
+ zodType = 'z.boolean()';
53
+ break;
54
+ case 'date':
55
+ zodType = 'z.string().datetime()'; // PocketBase sends dates as ISO strings
56
+ break;
57
+ case 'select':
58
+ if (field.options.values) {
59
+ const values = field.options.values.map((v: string) => `'${v}'`).join(', ');
60
+ zodType = `z.enum([${values}])`;
61
+ }
62
+ break;
63
+ case 'relation':
64
+ zodType = field.options.maxSelect === 1 ? 'z.string()' : 'z.array(z.string())';
65
+ break;
66
+ case 'file':
67
+ zodType = field.options.maxSelect === 1 ? 'z.string()' : 'z.array(z.string())';
68
+ break;
69
+ case 'json':
70
+ zodType = 'z.unknown()';
71
+ break;
72
+ }
73
+
74
+ if (!field.required) {
75
+ zodType += '.optional().nullable()';
76
+ }
77
+
78
+ fileContent += ` ${field.name}: ${zodType},\n`;
79
+ }
80
+
81
+ fileContent += `});\n\n`;
82
+ fileContent += `export type ${col.name.charAt(0).toUpperCase() + col.name.slice(1)} = z.infer<typeof ${col.name}Schema>;\n\n`;
83
+ }
84
+
85
+ const outputPath = path.resolve(process.cwd(), options.output);
86
+ fs.writeFileSync(outputPath, fileContent);
87
+ console.log(`✅ Schemas generated successfully at: ${outputPath}`);
88
+
89
+ } catch (error: any) {
90
+ console.error('❌ Error:', error.message);
91
+ process.exit(1);
92
+ }
93
+ });
94
+
95
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "pocketbase-to-zod",
3
+ "version": "1.0.0",
4
+ "description": "This project is an utility to generate Zod schemas from Pocketbase instance ",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "pb-to-zod": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc && chmod +x dist/index.js"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/ajomuch92/pocketbase-to-zod.git"
15
+ },
16
+ "keywords": [
17
+ "Zod",
18
+ "schemas",
19
+ "pocketbase",
20
+ "pb",
21
+ "validations",
22
+ "instance"
23
+ ],
24
+ "author": "Aarón Montes",
25
+ "license": "MIT",
26
+ "bugs": {
27
+ "url": "https://github.com/ajomuch92/pocketbase-to-zod/issues"
28
+ },
29
+ "homepage": "https://github.com/ajomuch92/pocketbase-to-zod#readme",
30
+ "dependencies": {
31
+ "commander": "^14.0.2",
32
+ "pocketbase": "^0.26.6",
33
+ "zod": "^4.3.5"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^25.0.9",
37
+ "ts-node": "^10.9.2",
38
+ "typescript": "^5.9.3"
39
+ }
40
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ "target": "ESNext",
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "outDir": "./dist",
8
+ "rootDir": "./",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "declaration": true
13
+ },
14
+ "include": ["index.ts"]
15
+ }