crudora 0.1.0-alpha.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -0
  3. package/dist/core/crudora.d.ts +24 -0
  4. package/dist/core/crudora.d.ts.map +1 -0
  5. package/dist/core/crudora.js +176 -0
  6. package/dist/core/crudora.js.map +1 -0
  7. package/dist/core/crudoraServer.d.ts +30 -0
  8. package/dist/core/crudoraServer.d.ts.map +1 -0
  9. package/dist/core/crudoraServer.js +83 -0
  10. package/dist/core/crudoraServer.js.map +1 -0
  11. package/dist/core/model.d.ts +20 -0
  12. package/dist/core/model.d.ts.map +1 -0
  13. package/dist/core/model.js +15 -0
  14. package/dist/core/model.js.map +1 -0
  15. package/dist/core/repository.d.ts +20 -0
  16. package/dist/core/repository.d.ts.map +1 -0
  17. package/dist/core/repository.js +42 -0
  18. package/dist/core/repository.js.map +1 -0
  19. package/dist/core/schemaGenerator.d.ts +6 -0
  20. package/dist/core/schemaGenerator.d.ts.map +1 -0
  21. package/dist/core/schemaGenerator.js +43 -0
  22. package/dist/core/schemaGenerator.js.map +1 -0
  23. package/dist/decorators/model.d.ts +9 -0
  24. package/dist/decorators/model.d.ts.map +1 -0
  25. package/dist/decorators/model.js +46 -0
  26. package/dist/decorators/model.js.map +1 -0
  27. package/dist/index.d.ts +10 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +20 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/scripts/copy-assets.js +27 -0
  32. package/dist/scripts/postinstall.js +14 -0
  33. package/dist/templates/schema.prisma +22 -0
  34. package/dist/types/model.type.d.ts +13 -0
  35. package/dist/types/model.type.d.ts.map +1 -0
  36. package/dist/types/model.type.js +3 -0
  37. package/dist/types/model.type.js.map +1 -0
  38. package/dist/utils/validation.d.ts +7 -0
  39. package/dist/utils/validation.d.ts.map +1 -0
  40. package/dist/utils/validation.js +67 -0
  41. package/dist/utils/validation.js.map +1 -0
  42. package/package.json +82 -0
  43. package/scripts/copy-assets.js +27 -0
  44. package/scripts/postinstall.js +14 -0
  45. package/templates/schema.prisma +22 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Muhammad Surya Jayadiprana
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # Crudora
2
+
3
+ Automatic CRUD API generator for TypeScript with Prisma - Build REST APIs in minutes, not hours.
4
+
5
+ [![npm version](https://badge.fury.io/js/crudora.svg)](https://badge.fury.io/js/crudora)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
8
+
9
+ ## ✨ Features
10
+
11
+ - 🚀 **Zero Configuration**: Generate CRUD APIs instantly
12
+ - 🎯 **Type-Safe**: Full TypeScript support with Prisma integration
13
+ - 🔧 **Flexible**: Support for both decorator and inheritance patterns
14
+ - 📊 **Auto Pagination**: Built-in pagination and filtering
15
+ - 🛡️ **Validation**: Automatic request validation with Zod
16
+ - 🔌 **Extensible**: Custom routes and middleware support
17
+ - 📖 **Schema Generation**: Auto-generate Prisma schemas from models
18
+ - 🗄️ **Repository Pattern**: Built-in repository for database operations
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install crudora prisma @prisma/client reflect-metadata
24
+ # or
25
+ yarn add crudora prisma @prisma/client reflect-metadata
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### Method 1: Simple Inheritance (Recommended)
31
+
32
+ ```typescript
33
+ import { CrudoraServer, Model } from "crudora";
34
+ import { PrismaClient } from "@prisma/client";
35
+
36
+ const prisma = new PrismaClient();
37
+
38
+ // Define your models
39
+ class User extends Model {
40
+ static tableName = "users";
41
+ static primaryKey = "id";
42
+ static timestamps = true;
43
+ static fillable = ["name", "email"];
44
+ static hidden = ["password"];
45
+ }
46
+
47
+ class Post extends Model {
48
+ static tableName = "posts";
49
+ static fillable = ["title", "content", "authorId"];
50
+ }
51
+
52
+ // Create server and register models
53
+ const server = new CrudoraServer({
54
+ port: 3000,
55
+ prisma: prisma,
56
+ cors: true,
57
+ basePath: "/api"
58
+ });
59
+
60
+ server
61
+ .registerModel(User, Post)
62
+ .generateRoutes()
63
+ .listen(() => {
64
+ console.log('Server running on port 3000');
65
+ });
66
+ ```
67
+
68
+ ### Method 2: Decorator Pattern
69
+
70
+ ```typescript
71
+ import "reflect-metadata";
72
+ import { CrudoraServer, Model, Field } from "crudora";
73
+ import { PrismaClient } from "@prisma/client";
74
+
75
+ const prisma = new PrismaClient();
76
+
77
+ @Model({ tableName: "users" })
78
+ class User {
79
+ @Field({ type: "uuid", primary: true })
80
+ id!: string;
81
+
82
+ @Field({ type: "string", required: true })
83
+ name!: string;
84
+
85
+ @Field({ type: "string", unique: true, required: true })
86
+ email!: string;
87
+
88
+ @Field({ type: "date" })
89
+ createdAt!: Date;
90
+
91
+ @Field({ type: "date" })
92
+ updatedAt!: Date;
93
+ }
94
+
95
+ const server = new CrudoraServer({
96
+ port: 3000,
97
+ prisma: prisma,
98
+ });
99
+
100
+ server
101
+ .registerModel(User)
102
+ .generateRoutes()
103
+ .listen();
104
+ ```
105
+
106
+ ## Generated API Endpoints
107
+
108
+ For each registered model, Crudora automatically generates:
109
+
110
+ - `GET /api/{tableName}` - List all records with pagination and filtering
111
+ - `GET /api/{tableName}/:id` - Get record by ID
112
+ - `POST /api/{tableName}` - Create new record
113
+ - `PUT /api/{tableName}/:id` - Update record
114
+ - `DELETE /api/{tableName}/:id` - Delete record
115
+
116
+ ### Query Parameters
117
+
118
+ - `skip` - Number of records to skip (pagination)
119
+ - `take` - Number of records to take (pagination)
120
+ - `orderBy` - Sort order (e.g., `createdAt:desc`)
121
+ - `where` - Filter conditions
122
+
123
+ ## Advanced Usage
124
+
125
+ ### Using Repositories
126
+
127
+ ```typescript
128
+ const crudora = server.getCrudora();
129
+ const userRepo = crudora.getRepository(User);
130
+
131
+ // Create user
132
+ const user = await userRepo.create({
133
+ name: "John Doe",
134
+ email: "john@example.com"
135
+ });
136
+
137
+ // Find users
138
+ const users = await userRepo.findAll({
139
+ skip: 0,
140
+ take: 10,
141
+ where: { active: true },
142
+ orderBy: { createdAt: 'desc' }
143
+ });
144
+
145
+ // Count users
146
+ const count = await userRepo.count({ active: true });
147
+ ```
148
+
149
+ ### Custom Routes
150
+
151
+ ```typescript
152
+ server
153
+ .get("/health", (req, res) => {
154
+ res.json({ status: "ok", timestamp: new Date() });
155
+ })
156
+ .post("/users/:id/activate", async (req, res) => {
157
+ const userRepo = server.getCrudora().getRepository(User);
158
+ const user = await userRepo.update(req.params.id, { active: true });
159
+ res.json(user);
160
+ });
161
+ ```
162
+
163
+ ### Schema Generation
164
+
165
+ ```typescript
166
+ // Generate Prisma schema from your models
167
+ const schema = server.getCrudora().generatePrismaSchema("postgresql");
168
+ console.log(schema);
169
+ ```
170
+
171
+ ### Validation
172
+
173
+ Crudora automatically generates Zod validation schemas:
174
+
175
+ ```typescript
176
+ const crudora = server.getCrudora();
177
+
178
+ // Get partial validation schema (for updates)
179
+ const partialSchema = crudora.getValidationSchema(User);
180
+
181
+ // Get strict validation schema (for creation)
182
+ const strictSchema = crudora.getStrictValidationSchema(User);
183
+ ```
184
+
185
+ ## Documentation
186
+
187
+ - [API Reference](./docs/api.md)
188
+ - [Model Definition Guide](./docs/models.md)
189
+ - [Custom Routes](./docs/custom-routes.md)
190
+ - [Deployment Guide](./docs/deployment.md)
191
+
192
+ ## Contributing
193
+
194
+ We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
195
+
196
+ ## License
197
+
198
+ MIT © [Crudora](https://github.com/suryamsj/crudora)
199
+
200
+ ---
201
+
202
+ **⚠️ Alpha Version - Not recommended for production use**
@@ -0,0 +1,24 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+ import { Express } from 'express';
3
+ import { z } from 'zod';
4
+ import { Repository } from './repository';
5
+ import { Model, ModelConstructor } from './model';
6
+ export declare class Crudora {
7
+ private prisma;
8
+ private models;
9
+ private repositories;
10
+ private customRoutes;
11
+ constructor(prisma?: PrismaClient);
12
+ registerModel(...modelClasses: ModelConstructor[]): this;
13
+ getRepository<T extends Model>(modelClass: ModelConstructor<T>): Repository<T>;
14
+ generatePrismaSchema(databaseProvider?: string): string;
15
+ getValidationSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<Partial<T>>;
16
+ getStrictValidationSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<T>;
17
+ get(path: string, handler: (req: any, res: any) => void): this;
18
+ post(path: string, handler: (req: any, res: any) => void): this;
19
+ put(path: string, handler: (req: any, res: any) => void): this;
20
+ delete(path: string, handler: (req: any, res: any) => void): this;
21
+ patch(path: string, handler: (req: any, res: any) => void): this;
22
+ generateRoutes(app: Express, basePath?: string): void;
23
+ }
24
+ //# sourceMappingURL=crudora.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crudora.d.ts","sourceRoot":"","sources":["../../src/core/crudora.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElD,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,YAAY,CAIZ;gBAEI,MAAM,CAAC,EAAE,YAAY;IAQjC,aAAa,CAAC,GAAG,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAWxD,aAAa,CAAC,CAAC,SAAS,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IAQ9E,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;IAKvD,mBAAmB,CAAC,CAAC,SAAS,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAI5F,yBAAyB,CAAC,CAAC,SAAS,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAKzF,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK9D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK/D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK9D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAKjE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAMhE,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,GAAE,MAAe,GAAG,IAAI;CA+G9D"}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Crudora = void 0;
4
+ const zod_1 = require("zod");
5
+ const repository_1 = require("./repository");
6
+ const schemaGenerator_1 = require("./schemaGenerator");
7
+ const validation_1 = require("../utils/validation");
8
+ class Crudora {
9
+ constructor(prisma) {
10
+ this.models = new Map();
11
+ this.repositories = new Map();
12
+ this.customRoutes = [];
13
+ if (!prisma) {
14
+ console.warn('⚠️ No Prisma client provided. Make sure to install @prisma/client and prisma, then initialize PrismaClient.');
15
+ throw new Error('PrismaClient is required. Please provide a PrismaClient instance.');
16
+ }
17
+ this.prisma = prisma;
18
+ }
19
+ registerModel(...modelClasses) {
20
+ for (const modelClass of modelClasses) {
21
+ const modelName = modelClass.name;
22
+ this.models.set(modelName, modelClass);
23
+ const repository = new repository_1.Repository(modelClass, this.prisma);
24
+ this.repositories.set(modelName, repository);
25
+ }
26
+ return this;
27
+ }
28
+ getRepository(modelClass) {
29
+ const repository = this.repositories.get(modelClass.name);
30
+ if (!repository) {
31
+ throw new Error(`Repository for ${modelClass.name} not found. Did you register the model?`);
32
+ }
33
+ return repository;
34
+ }
35
+ generatePrismaSchema(databaseProvider) {
36
+ const modelClasses = Array.from(this.models.values());
37
+ return schemaGenerator_1.SchemaGenerator.generatePrismaSchema(modelClasses, databaseProvider);
38
+ }
39
+ getValidationSchema(modelClass) {
40
+ return validation_1.ValidationGenerator.generateZodSchema(modelClass);
41
+ }
42
+ getStrictValidationSchema(modelClass) {
43
+ return validation_1.ValidationGenerator.generateStrictZodSchema(modelClass);
44
+ }
45
+ // Custom route methods
46
+ get(path, handler) {
47
+ this.customRoutes.push({ method: 'GET', path, handler });
48
+ return this;
49
+ }
50
+ post(path, handler) {
51
+ this.customRoutes.push({ method: 'POST', path, handler });
52
+ return this;
53
+ }
54
+ put(path, handler) {
55
+ this.customRoutes.push({ method: 'PUT', path, handler });
56
+ return this;
57
+ }
58
+ delete(path, handler) {
59
+ this.customRoutes.push({ method: 'DELETE', path, handler });
60
+ return this;
61
+ }
62
+ patch(path, handler) {
63
+ this.customRoutes.push({ method: 'PATCH', path, handler });
64
+ return this;
65
+ }
66
+ // Auto-generate REST API routes
67
+ generateRoutes(app, basePath = '/api') {
68
+ // Generate CRUD routes for models
69
+ for (const [modelName, modelClass] of this.models) {
70
+ const repository = this.getRepository(modelClass);
71
+ const validationSchema = this.getValidationSchema(modelClass);
72
+ const routePath = `${basePath}/${modelClass.getTableName()}`;
73
+ // GET /api/model - List all
74
+ app.get(routePath, async (req, res) => {
75
+ try {
76
+ const { page = 1, limit = 10, ...filters } = req.query;
77
+ const skip = (Number(page) - 1) * Number(limit);
78
+ const items = await repository.findAll({
79
+ skip,
80
+ take: Number(limit),
81
+ where: filters
82
+ });
83
+ const total = await repository.count(filters);
84
+ res.json({
85
+ data: items,
86
+ pagination: {
87
+ page: Number(page),
88
+ limit: Number(limit),
89
+ total,
90
+ pages: Math.ceil(total / Number(limit))
91
+ }
92
+ });
93
+ }
94
+ catch (error) {
95
+ res.status(500).json({ error: 'Internal server error' });
96
+ }
97
+ });
98
+ // GET /api/model/:id - Get by ID
99
+ app.get(`${routePath}/:id`, async (req, res) => {
100
+ try {
101
+ const item = await repository.findById(req.params.id);
102
+ if (!item) {
103
+ return res.status(404).json({ error: 'Not found' });
104
+ }
105
+ res.json(item);
106
+ }
107
+ catch (error) {
108
+ res.status(500).json({ error: 'Internal server error' });
109
+ }
110
+ });
111
+ // POST /api/model - Create (gunakan strict validation)
112
+ app.post(routePath, async (req, res) => {
113
+ try {
114
+ const strictValidationSchema = this.getStrictValidationSchema(modelClass);
115
+ const validatedData = strictValidationSchema.parse(req.body);
116
+ const item = await repository.create(validatedData);
117
+ res.status(201).json(item);
118
+ }
119
+ catch (error) {
120
+ if (error instanceof zod_1.z.ZodError) {
121
+ return res.status(400).json({ error: 'Validation error', details: error.issues });
122
+ }
123
+ res.status(500).json({ error: 'Internal server error' });
124
+ }
125
+ });
126
+ // PUT /api/model/:id - Update (gunakan partial validation)
127
+ app.put(`${routePath}/:id`, async (req, res) => {
128
+ try {
129
+ const validationSchema = this.getValidationSchema(modelClass);
130
+ const validatedData = validationSchema.parse(req.body);
131
+ const item = await repository.update(req.params.id, validatedData);
132
+ res.json(item);
133
+ }
134
+ catch (error) {
135
+ if (error instanceof zod_1.z.ZodError) {
136
+ return res.status(400).json({ error: 'Validation error', details: error.issues });
137
+ }
138
+ res.status(500).json({ error: 'Internal server error' });
139
+ }
140
+ });
141
+ // DELETE /api/model/:id - Delete
142
+ app.delete(`${routePath}/:id`, async (req, res) => {
143
+ try {
144
+ await repository.delete(req.params.id);
145
+ res.status(204).send();
146
+ }
147
+ catch (error) {
148
+ res.status(500).json({ error: 'Internal server error' });
149
+ }
150
+ });
151
+ }
152
+ // Generate custom routes
153
+ for (const route of this.customRoutes) {
154
+ const fullPath = `${basePath}${route.path}`;
155
+ switch (route.method.toLowerCase()) {
156
+ case 'get':
157
+ app.get(fullPath, route.handler);
158
+ break;
159
+ case 'post':
160
+ app.post(fullPath, route.handler);
161
+ break;
162
+ case 'put':
163
+ app.put(fullPath, route.handler);
164
+ break;
165
+ case 'delete':
166
+ app.delete(fullPath, route.handler);
167
+ break;
168
+ case 'patch':
169
+ app.patch(fullPath, route.handler);
170
+ break;
171
+ }
172
+ }
173
+ }
174
+ }
175
+ exports.Crudora = Crudora;
176
+ //# sourceMappingURL=crudora.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crudora.js","sourceRoot":"","sources":["../../src/core/crudora.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { Express } from 'express';
2
+ import { Crudora } from './crudora';
3
+ import { PrismaClient } from '@prisma/client';
4
+ import { ModelConstructor } from './model';
5
+ export interface CrudoraServerConfig {
6
+ port?: number;
7
+ cors?: boolean;
8
+ bodyParser?: boolean;
9
+ prisma?: PrismaClient;
10
+ basePath?: string;
11
+ }
12
+ export declare class CrudoraServer {
13
+ private app;
14
+ private crudora;
15
+ private config;
16
+ constructor(config?: CrudoraServerConfig);
17
+ private setupMiddleware;
18
+ registerModel(...modelClasses: ModelConstructor[]): this;
19
+ generateRoutes(): this;
20
+ use(middleware: any): this;
21
+ listen(callback?: () => void): void;
22
+ getApp(): Express;
23
+ getCrudora(): Crudora;
24
+ get(path: string, handler: (req: any, res: any) => void): this;
25
+ post(path: string, handler: (req: any, res: any) => void): this;
26
+ put(path: string, handler: (req: any, res: any) => void): this;
27
+ delete(path: string, handler: (req: any, res: any) => void): this;
28
+ patch(path: string, handler: (req: any, res: any) => void): this;
29
+ }
30
+ //# sourceMappingURL=crudoraServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crudoraServer.d.ts","sourceRoot":"","sources":["../../src/core/crudoraServer.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAS,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,GAAE,mBAAwB;IAO5C,OAAO,CAAC,eAAe;IAoBvB,aAAa,CAAC,GAAG,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAKxD,cAAc,IAAI,IAAI;IAKtB,GAAG,CAAC,UAAU,EAAE,GAAG,GAAG,IAAI;IAK1B,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAQnC,MAAM,IAAI,OAAO;IAIjB,UAAU,IAAI,OAAO;IAIrB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK9D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK/D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAK9D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAKjE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;CAIjE"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CrudoraServer = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const crudora_1 = require("./crudora");
9
+ class CrudoraServer {
10
+ constructor(config = {}) {
11
+ this.config = { port: 3000, cors: true, bodyParser: true, basePath: '/api', ...config };
12
+ this.app = (0, express_1.default)();
13
+ this.crudora = new crudora_1.Crudora(config.prisma);
14
+ this.setupMiddleware();
15
+ }
16
+ setupMiddleware() {
17
+ if (this.config.bodyParser) {
18
+ this.app.use(express_1.default.json());
19
+ this.app.use(express_1.default.urlencoded({ extended: true }));
20
+ }
21
+ if (this.config.cors) {
22
+ this.app.use((req, res, next) => {
23
+ res.header('Access-Control-Allow-Origin', '*');
24
+ res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
25
+ res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
26
+ if (req.method === 'OPTIONS') {
27
+ res.sendStatus(200);
28
+ }
29
+ else {
30
+ next();
31
+ }
32
+ });
33
+ }
34
+ }
35
+ registerModel(...modelClasses) {
36
+ this.crudora.registerModel(...modelClasses);
37
+ return this;
38
+ }
39
+ generateRoutes() {
40
+ this.crudora.generateRoutes(this.app, this.config.basePath);
41
+ return this;
42
+ }
43
+ use(middleware) {
44
+ this.app.use(middleware);
45
+ return this;
46
+ }
47
+ listen(callback) {
48
+ this.app.listen(this.config.port, () => {
49
+ console.log(`🚀 Crudora server running on port ${this.config.port}`);
50
+ console.log(`📚 API available at http://localhost:${this.config.port}${this.config.basePath}`);
51
+ if (callback)
52
+ callback();
53
+ });
54
+ }
55
+ getApp() {
56
+ return this.app;
57
+ }
58
+ getCrudora() {
59
+ return this.crudora;
60
+ }
61
+ get(path, handler) {
62
+ this.crudora.get(path, handler);
63
+ return this;
64
+ }
65
+ post(path, handler) {
66
+ this.crudora.post(path, handler);
67
+ return this;
68
+ }
69
+ put(path, handler) {
70
+ this.crudora.put(path, handler);
71
+ return this;
72
+ }
73
+ delete(path, handler) {
74
+ this.crudora.delete(path, handler);
75
+ return this;
76
+ }
77
+ patch(path, handler) {
78
+ this.crudora.patch(path, handler);
79
+ return this;
80
+ }
81
+ }
82
+ exports.CrudoraServer = CrudoraServer;
83
+ //# sourceMappingURL=crudoraServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crudoraServer.js","sourceRoot":"","sources":["../../src/core/crudoraServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export declare abstract class Model {
2
+ static tableName?: string;
3
+ static primaryKey?: string;
4
+ static timestamps?: boolean;
5
+ static fillable?: string[];
6
+ static hidden?: string[];
7
+ static getTableName(): string;
8
+ static getPrimaryKey(): string;
9
+ }
10
+ export type ModelConstructor<T extends Model = Model> = {
11
+ new (): T;
12
+ tableName?: string;
13
+ primaryKey?: string;
14
+ timestamps?: boolean;
15
+ fillable?: string[];
16
+ hidden?: string[];
17
+ getTableName(): string;
18
+ getPrimaryKey(): string;
19
+ } & typeof Model;
20
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,8BAAsB,KAAK;IACzB,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,CAAQ;IAClC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAQ;IACnC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,MAAM,CAAC,YAAY,IAAI,MAAM;IAI7B,MAAM,CAAC,aAAa,IAAI,MAAM;CAG/B;AAGD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,IAAI;IACtD,QAAQ,CAAC,CAAC;IACV,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,IAAI,MAAM,CAAC;IACvB,aAAa,IAAI,MAAM,CAAC;CACzB,GAAG,OAAO,KAAK,CAAC"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Model = void 0;
4
+ class Model {
5
+ static getTableName() {
6
+ return this.tableName || this.name.toLowerCase() + 's';
7
+ }
8
+ static getPrimaryKey() {
9
+ return this.primaryKey || 'id';
10
+ }
11
+ }
12
+ exports.Model = Model;
13
+ Model.primaryKey = 'id';
14
+ Model.timestamps = true;
15
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":";;;AAAA,MAAsB,KAAK;IAOzB,MAAM,CAAC,YAAY;QACjB,OAAO,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,aAAa;QAClB,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IACjC,CAAC;;AAbH,sBAcC;AAZQ,gBAAU,GAAY,IAAI,CAAC;AAC3B,gBAAU,GAAa,IAAI,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+ import { Model, ModelConstructor } from './model';
3
+ export declare class Repository<T extends Model> {
4
+ private prisma;
5
+ private modelName;
6
+ private modelClass;
7
+ constructor(modelClass: ModelConstructor<T>, prisma: PrismaClient);
8
+ create(data: Partial<T>): Promise<T>;
9
+ findById(id: string): Promise<T | null>;
10
+ findAll(options?: {
11
+ skip?: number;
12
+ take?: number;
13
+ where?: any;
14
+ orderBy?: any;
15
+ }): Promise<T[]>;
16
+ update(id: string, data: Partial<T>): Promise<T>;
17
+ delete(id: string): Promise<T>;
18
+ count(where?: any): Promise<number>;
19
+ }
20
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElD,qBAAa,UAAU,CAAC,CAAC,SAAS,KAAK;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY;IAS3D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAKpC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKvC,OAAO,CAAC,OAAO,CAAC,EAAE;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,GAAG,CAAC;QACZ,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKV,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAQhD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAK9B,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;CAI1C"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Repository = void 0;
4
+ const model_1 = require("../decorators/model");
5
+ class Repository {
6
+ constructor(modelClass, prisma) {
7
+ this.prisma = prisma;
8
+ this.modelClass = modelClass;
9
+ // Try to get metadata from decorator first, then fallback to static methods
10
+ const metadata = (0, model_1.getModelMetadata)(modelClass);
11
+ this.modelName = metadata?.tableName || modelClass.getTableName();
12
+ }
13
+ async create(data) {
14
+ const model = this.prisma[this.modelName];
15
+ return await model.create({ data });
16
+ }
17
+ async findById(id) {
18
+ const model = this.prisma[this.modelName];
19
+ return await model.findUnique({ where: { id } });
20
+ }
21
+ async findAll(options) {
22
+ const model = this.prisma[this.modelName];
23
+ return await model.findMany(options);
24
+ }
25
+ async update(id, data) {
26
+ const model = this.prisma[this.modelName];
27
+ return await model.update({
28
+ where: { id },
29
+ data
30
+ });
31
+ }
32
+ async delete(id) {
33
+ const model = this.prisma[this.modelName];
34
+ return await model.delete({ where: { id } });
35
+ }
36
+ async count(where) {
37
+ const model = this.prisma[this.modelName];
38
+ return await model.count({ where });
39
+ }
40
+ }
41
+ exports.Repository = Repository;
42
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":";;;AACA,+CAAuD;AAGvD,MAAa,UAAU;IAKrB,YAAY,UAA+B,EAAE,MAAoB;QAC/D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAE7B,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,IAAA,wBAAgB,EAAC,UAAiB,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,QAAQ,EAAE,SAAS,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAgB;QAC3B,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAKb;QACC,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAAgB;QACvC,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC;YACxB,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAW;QACrB,MAAM,KAAK,GAAI,IAAI,CAAC,MAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnD,OAAO,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtC,CAAC;CACF;AAnDD,gCAmDC"}
@@ -0,0 +1,6 @@
1
+ import { Model } from './model';
2
+ export declare class SchemaGenerator {
3
+ static generatePrismaSchema(models: (typeof Model)[], databaseProvider?: string): string;
4
+ private static generateModelSchemaFromClass;
5
+ }
6
+ //# sourceMappingURL=schemaGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaGenerator.d.ts","sourceRoot":"","sources":["../../src/core/schemaGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,qBAAa,eAAe;IAC1B,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,OAAO,KAAK,CAAC,EAAE,EAAE,gBAAgB,GAAE,MAAiB,GAAG,MAAM;IAmBlG,OAAO,CAAC,MAAM,CAAC,4BAA4B;CA2B5C"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaGenerator = void 0;
4
+ class SchemaGenerator {
5
+ static generatePrismaSchema(models, databaseProvider = 'sqlite') {
6
+ let schema = `// Auto-generated Prisma schema\n// Generated by Crudora Framework\n\n`;
7
+ schema += `generator client {\n provider = "prisma-client-js"\n}\n\n`;
8
+ // Fix: Use the provided database provider directly
9
+ if (databaseProvider === 'sqlite') {
10
+ schema += `datasource db {\n provider = "sqlite"\n url = env("DATABASE_URL")\n}\n\n`;
11
+ }
12
+ else {
13
+ schema += `datasource db {\n provider = "${databaseProvider}"\n url = env("DATABASE_URL")\n}\n\n`;
14
+ }
15
+ for (const model of models) {
16
+ schema += this.generateModelSchemaFromClass(model);
17
+ }
18
+ return schema;
19
+ }
20
+ static generateModelSchemaFromClass(modelClass) {
21
+ const tableName = modelClass.getTableName();
22
+ const primaryKey = modelClass.getPrimaryKey();
23
+ let schema = `model ${modelClass.name} {\n`;
24
+ // Add primary key
25
+ schema += ` ${primaryKey} String @id @default(uuid())\n`;
26
+ // Add common fields (you can customize this based on your needs)
27
+ schema += ` createdAt DateTime @default(now())\n`;
28
+ schema += ` updatedAt DateTime @updatedAt\n`;
29
+ // Add custom fields if defined in static properties
30
+ if (modelClass.fillable) {
31
+ for (const field of modelClass.fillable) {
32
+ if (field !== primaryKey) {
33
+ schema += ` ${field} String?\n`;
34
+ }
35
+ }
36
+ }
37
+ schema += `\n @@map("${tableName}")\n`;
38
+ schema += `}\n\n`;
39
+ return schema;
40
+ }
41
+ }
42
+ exports.SchemaGenerator = SchemaGenerator;
43
+ //# sourceMappingURL=schemaGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaGenerator.js","sourceRoot":"","sources":["../../src/core/schemaGenerator.ts"],"names":[],"mappings":";;;AAEA,MAAa,eAAe;IAC1B,MAAM,CAAC,oBAAoB,CAAC,MAAwB,EAAE,mBAA2B,QAAQ;QACvF,IAAI,MAAM,GAAG,wEAAwE,CAAC;QAEtF,MAAM,IAAI,4DAA4D,CAAC;QAEvE,mDAAmD;QACnD,IAAI,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,IAAI,4EAA4E,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,kCAAkC,gBAAgB,uCAAuC,CAAC;QACtG,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,MAAM,CAAC,4BAA4B,CAAC,UAAwB;QAClE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,EAAE,CAAC;QAE9C,IAAI,MAAM,GAAG,SAAS,UAAU,CAAC,IAAI,MAAM,CAAC;QAE5C,kBAAkB;QAClB,MAAM,IAAI,KAAK,UAAU,gCAAgC,CAAC;QAE1D,iEAAiE;QACjE,MAAM,IAAI,wCAAwC,CAAC;QACnD,MAAM,IAAI,mCAAmC,CAAC;QAE9C,oDAAoD;QACpD,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBACxC,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,KAAK,YAAY,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,IAAI,cAAc,SAAS,MAAM,CAAC;QACxC,MAAM,IAAI,OAAO,CAAC;QAElB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA/CD,0CA+CC"}
@@ -0,0 +1,9 @@
1
+ import 'reflect-metadata';
2
+ import { FieldOptions, ModelOptions } from '../types/model.type';
3
+ export declare function Model(options?: ModelOptions): <T extends {
4
+ new (...args: any[]): {};
5
+ }>(constructor: T) => T;
6
+ export declare function Field(options: FieldOptions): (target: any, context: any) => void;
7
+ export declare function getModelMetadata(target: any): any;
8
+ export declare function getFieldMetadata(target: any): any;
9
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/decorators/model.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKjE,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,IAC7B,CAAC,SAAS;IAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;CAAE,EAAE,aAAa,CAAC,OAQxE;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,IACxB,QAAQ,GAAG,EAAE,SAAS,GAAG,UAiB3C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,OAE3C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,OAE3C"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Model = Model;
4
+ exports.Field = Field;
5
+ exports.getModelMetadata = getModelMetadata;
6
+ exports.getFieldMetadata = getFieldMetadata;
7
+ require("reflect-metadata");
8
+ const MODEL_METADATA_KEY = Symbol('model');
9
+ const FIELD_METADATA_KEY = Symbol('field');
10
+ function Model(options = {}) {
11
+ return function (constructor) {
12
+ Reflect.defineMetadata(MODEL_METADATA_KEY, {
13
+ tableName: options.tableName || constructor.name.toLowerCase(),
14
+ timestamps: options.timestamps !== false,
15
+ constructor
16
+ }, constructor);
17
+ return constructor;
18
+ };
19
+ }
20
+ function Field(options) {
21
+ return function (target, context) {
22
+ // Support both old and new decorator syntax
23
+ if (typeof context === 'string') {
24
+ // Old decorator syntax (target, propertyKey)
25
+ const propertyKey = context;
26
+ const existingFields = Reflect.getMetadata(FIELD_METADATA_KEY, target.constructor) || {};
27
+ existingFields[propertyKey] = options;
28
+ Reflect.defineMetadata(FIELD_METADATA_KEY, existingFields, target.constructor);
29
+ }
30
+ else {
31
+ // New decorator syntax (target, context)
32
+ const propertyKey = context.name;
33
+ const constructor = target.constructor;
34
+ const existingFields = Reflect.getMetadata(FIELD_METADATA_KEY, constructor) || {};
35
+ existingFields[propertyKey] = options;
36
+ Reflect.defineMetadata(FIELD_METADATA_KEY, existingFields, constructor);
37
+ }
38
+ };
39
+ }
40
+ function getModelMetadata(target) {
41
+ return Reflect.getMetadata(MODEL_METADATA_KEY, target);
42
+ }
43
+ function getFieldMetadata(target) {
44
+ return Reflect.getMetadata(FIELD_METADATA_KEY, target) || {};
45
+ }
46
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/decorators/model.ts"],"names":[],"mappings":";;AAMA,sBASC;AAED,sBAkBC;AAED,4CAEC;AAED,4CAEC;AA3CD,4BAA0B;AAG1B,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AAC3C,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AAE3C,SAAgB,KAAK,CAAC,UAAwB,EAAE;IAC9C,OAAO,UAAkD,WAAc;QACrE,OAAO,CAAC,cAAc,CAAC,kBAAkB,EAAE;YACzC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE;YAC9D,UAAU,EAAE,OAAO,CAAC,UAAU,KAAK,KAAK;YACxC,WAAW;SACZ,EAAE,WAAW,CAAC,CAAC;QAChB,OAAO,WAAW,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,KAAK,CAAC,OAAqB;IACzC,OAAO,UAAU,MAAW,EAAE,OAAY;QACxC,4CAA4C;QAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,6CAA6C;YAC7C,MAAM,WAAW,GAAG,OAAO,CAAC;YAC5B,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACzF,cAAc,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;YACtC,OAAO,CAAC,cAAc,CAAC,kBAAkB,EAAE,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QACjF,CAAC;aAAM,CAAC;YACN,yCAAyC;YACzC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YACjC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;YACvC,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;YAClF,cAAc,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;YACtC,OAAO,CAAC,cAAc,CAAC,kBAAkB,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAAC,MAAW;IAC1C,OAAO,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,gBAAgB,CAAC,MAAW;IAC1C,OAAO,OAAO,CAAC,WAAW,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { Crudora } from './core/crudora';
2
+ export { CrudoraServer } from './core/crudoraServer';
3
+ export { Repository } from './core/repository';
4
+ export { SchemaGenerator } from './core/schemaGenerator';
5
+ export { ValidationGenerator } from './utils/validation';
6
+ export { Model } from './core/model';
7
+ export type { CrudoraServerConfig } from './core/crudoraServer';
8
+ export { Model as ModelDecorator, Field } from './decorators/model';
9
+ export type { ModelOptions, FieldOptions } from './types/model.type';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Field = exports.ModelDecorator = exports.Model = exports.ValidationGenerator = exports.SchemaGenerator = exports.Repository = exports.CrudoraServer = exports.Crudora = void 0;
4
+ var crudora_1 = require("./core/crudora");
5
+ Object.defineProperty(exports, "Crudora", { enumerable: true, get: function () { return crudora_1.Crudora; } });
6
+ var crudoraServer_1 = require("./core/crudoraServer");
7
+ Object.defineProperty(exports, "CrudoraServer", { enumerable: true, get: function () { return crudoraServer_1.CrudoraServer; } });
8
+ var repository_1 = require("./core/repository");
9
+ Object.defineProperty(exports, "Repository", { enumerable: true, get: function () { return repository_1.Repository; } });
10
+ var schemaGenerator_1 = require("./core/schemaGenerator");
11
+ Object.defineProperty(exports, "SchemaGenerator", { enumerable: true, get: function () { return schemaGenerator_1.SchemaGenerator; } });
12
+ var validation_1 = require("./utils/validation");
13
+ Object.defineProperty(exports, "ValidationGenerator", { enumerable: true, get: function () { return validation_1.ValidationGenerator; } });
14
+ var model_1 = require("./core/model"); // New export
15
+ Object.defineProperty(exports, "Model", { enumerable: true, get: function () { return model_1.Model; } });
16
+ // Keep decorator exports for backward compatibility
17
+ var model_2 = require("./decorators/model");
18
+ Object.defineProperty(exports, "ModelDecorator", { enumerable: true, get: function () { return model_2.Model; } });
19
+ Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return model_2.Field; } });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,0CAAyC;AAAhC,kGAAA,OAAO,OAAA;AAChB,sDAAqD;AAA5C,8GAAA,aAAa,OAAA;AACtB,gDAA+C;AAAtC,wGAAA,UAAU,OAAA;AACnB,0DAAyD;AAAhD,kHAAA,eAAe,OAAA;AACxB,iDAAyD;AAAhD,iHAAA,mBAAmB,OAAA;AAC5B,sCAAqC,CAAC,aAAa;AAA1C,8FAAA,KAAK,OAAA;AAGd,oDAAoD;AACpD,4CAAoE;AAA3D,uGAAA,KAAK,OAAkB;AAAE,8FAAA,KAAK,OAAA"}
@@ -0,0 +1,27 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function copyDir(src, dest) {
5
+ if (!fs.existsSync(dest)) {
6
+ fs.mkdirSync(dest, { recursive: true });
7
+ }
8
+
9
+ const entries = fs.readdirSync(src, { withFileTypes: true });
10
+
11
+ for (const entry of entries) {
12
+ const srcPath = path.join(src, entry.name);
13
+ const destPath = path.join(dest, entry.name);
14
+
15
+ if (entry.isDirectory()) {
16
+ copyDir(srcPath, destPath);
17
+ } else {
18
+ fs.copyFileSync(srcPath, destPath);
19
+ }
20
+ }
21
+ }
22
+
23
+ // Copy templates
24
+ copyDir('templates', 'dist/templates');
25
+ copyDir('scripts', 'dist/scripts');
26
+
27
+ console.log('✅ Assets copied to dist/');
@@ -0,0 +1,14 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const templatePath = path.join(__dirname, '..', 'templates', 'schema.prisma');
5
+ const targetPath = path.join(process.cwd(), 'prisma', 'schema.prisma');
6
+
7
+ // Only copy if prisma directory doesn't exist
8
+ if (!fs.existsSync(path.dirname(targetPath))) {
9
+ console.log('📋 Creating default Prisma schema...');
10
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
11
+ fs.copyFileSync(templatePath, targetPath);
12
+ console.log('✅ Default schema.prisma created in prisma/schema.prisma');
13
+ console.log('🔧 Don\'t forget to set your DATABASE_URL in .env file');
14
+ }
@@ -0,0 +1,22 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client-js"
6
+ }
7
+
8
+ datasource db {
9
+ provider = "sqlite"
10
+ url = env("DATABASE_URL")
11
+ }
12
+
13
+ // Add your models here
14
+ // Example:
15
+ // model User {
16
+ // id String @id @default(uuid())
17
+ // name String
18
+ // email String @unique
19
+ // password String
20
+ // createdAt DateTime @default(now())
21
+ // updatedAt DateTime @updatedAt
22
+ // }
@@ -0,0 +1,13 @@
1
+ export interface ModelOptions {
2
+ tableName?: string;
3
+ timestamps?: boolean;
4
+ }
5
+ export interface FieldOptions {
6
+ type: 'string' | 'number' | 'boolean' | 'date' | 'uuid';
7
+ required?: boolean;
8
+ unique?: boolean;
9
+ default?: any;
10
+ length?: number;
11
+ primary?: boolean;
12
+ }
13
+ //# sourceMappingURL=model.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.type.d.ts","sourceRoot":"","sources":["../../src/types/model.type.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=model.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.type.js","sourceRoot":"","sources":["../../src/types/model.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ export declare class ValidationGenerator {
3
+ static generateZodSchema<T>(modelClass: new () => T): z.ZodType<Partial<T>>;
4
+ static generateStrictZodSchema<T>(modelClass: new () => T): z.ZodType<T>;
5
+ private static createZodField;
6
+ }
7
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAgB3E,MAAM,CAAC,uBAAuB,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAoBxE,OAAO,CAAC,MAAM,CAAC,cAAc;CAiC9B"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationGenerator = void 0;
4
+ const zod_1 = require("zod");
5
+ const model_1 = require("../decorators/model");
6
+ class ValidationGenerator {
7
+ static generateZodSchema(modelClass) {
8
+ const fieldMetadata = (0, model_1.getFieldMetadata)(modelClass);
9
+ const schemaFields = {};
10
+ // If no field metadata, return empty partial schema
11
+ if (Object.keys(fieldMetadata).length === 0) {
12
+ return zod_1.z.object({}).partial();
13
+ }
14
+ for (const [fieldName, options] of Object.entries(fieldMetadata)) {
15
+ schemaFields[fieldName] = this.createZodField(options);
16
+ }
17
+ return zod_1.z.object(schemaFields).partial();
18
+ }
19
+ static generateStrictZodSchema(modelClass) {
20
+ const fieldMetadata = (0, model_1.getFieldMetadata)(modelClass);
21
+ const schemaFields = {};
22
+ // If no field metadata, return empty schema
23
+ if (Object.keys(fieldMetadata).length === 0) {
24
+ return zod_1.z.object({});
25
+ }
26
+ for (const [fieldName, options] of Object.entries(fieldMetadata)) {
27
+ // For strict schema, skip primary key fields that are auto-generated
28
+ if (options.primary && options.type === 'uuid') {
29
+ continue;
30
+ }
31
+ schemaFields[fieldName] = this.createZodField(options);
32
+ }
33
+ return zod_1.z.object(schemaFields);
34
+ }
35
+ static createZodField(options) {
36
+ let field;
37
+ switch (options.type) {
38
+ case 'string':
39
+ field = zod_1.z.string();
40
+ if (options.length) {
41
+ field = field.max(options.length);
42
+ }
43
+ break;
44
+ case 'number':
45
+ field = zod_1.z.number();
46
+ break;
47
+ case 'boolean':
48
+ field = zod_1.z.boolean();
49
+ break;
50
+ case 'date':
51
+ field = zod_1.z.date();
52
+ break;
53
+ case 'uuid':
54
+ field = zod_1.z.string().uuid();
55
+ break;
56
+ default:
57
+ field = zod_1.z.string();
58
+ }
59
+ // If required is explicitly false, make field optional
60
+ if (options.required === false) {
61
+ field = field.optional();
62
+ }
63
+ return field;
64
+ }
65
+ }
66
+ exports.ValidationGenerator = ValidationGenerator;
67
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,+CAAuD;AAGvD,MAAa,mBAAmB;IAC9B,MAAM,CAAC,iBAAiB,CAAI,UAAuB;QACjD,MAAM,aAAa,GAAG,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC;QACnD,MAAM,YAAY,GAAiC,EAAE,CAAC;QAEtD,oDAAoD;QACpD,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAA2B,CAAC;QACzD,CAAC;QAED,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAA6B,EAAE,CAAC;YAC7F,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,OAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAA2B,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,uBAAuB,CAAI,UAAuB;QACvD,MAAM,aAAa,GAAG,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC;QACnD,MAAM,YAAY,GAAiC,EAAE,CAAC;QAEtD,4CAA4C;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,OAAC,CAAC,MAAM,CAAC,EAAE,CAAiB,CAAC;QACtC,CAAC;QAED,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAA6B,EAAE,CAAC;YAC7F,qEAAqE;YACrE,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YACD,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,OAAC,CAAC,MAAM,CAAC,YAAY,CAAiB,CAAC;IAChD,CAAC;IAEO,MAAM,CAAC,cAAc,CAAC,OAAqB;QACjD,IAAI,KAAmB,CAAC;QAExB,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,QAAQ;gBACX,KAAK,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnB,KAAK,GAAI,KAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACrD,CAAC;gBACD,MAAM;YACR,KAAK,QAAQ;gBACX,KAAK,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM;YACR,KAAK,SAAS;gBACZ,KAAK,GAAG,OAAC,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM;YACR,KAAK,MAAM;gBACT,KAAK,GAAG,OAAC,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM;YACR,KAAK,MAAM;gBACT,KAAK,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;gBAC1B,MAAM;YACR;gBACE,KAAK,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,uDAAuD;QACvD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC/B,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAtED,kDAsEC"}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "crudora",
3
+ "version": "0.1.0-alpha.1",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "files": [
7
+ "dist",
8
+ "README.md",
9
+ "LICENSE",
10
+ "templates",
11
+ "scripts"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc && node scripts/copy-assets.js",
15
+ "copy-assets": "node scripts/copy-assets.js",
16
+ "build:watch": "tsc --watch",
17
+ "clean": "rimraf dist",
18
+ "prebuild": "npm run clean",
19
+ "prepublishOnly": "npm run build",
20
+ "dev": "ts-node src/index.ts",
21
+ "test": "jest",
22
+ "test:watch": "jest --watch",
23
+ "test:coverage": "jest --coverage",
24
+ "lint": "eslint src/**/*.ts",
25
+ "format": "prettier --write src/**/*.ts",
26
+ "postinstall": "node scripts/postinstall.js"
27
+ },
28
+ "keywords": [
29
+ "crud",
30
+ "api",
31
+ "typescript",
32
+ "prisma",
33
+ "express",
34
+ "framework",
35
+ "backend",
36
+ "rest-api",
37
+ "orm",
38
+ "validation",
39
+ "zod",
40
+ "decorators",
41
+ "auto-generation"
42
+ ],
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/suryamsj/crudora.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/suryamsj/crudora/issues"
49
+ },
50
+ "homepage": "https://github.com/suryamsj/crudora#readme",
51
+ "author": {
52
+ "name": "Muhammad Surya J",
53
+ "url": "https://suryamsj.my.id"
54
+ },
55
+ "license": "MIT",
56
+ "description": "TypeScript framework for automated CRUD API generation with Prisma and Express",
57
+ "dependencies": {
58
+ "@types/express": "^5.0.3",
59
+ "express": "^5.1.0",
60
+ "reflect-metadata": "^0.2.2",
61
+ "zod": "^4.0.5"
62
+ },
63
+ "devDependencies": {
64
+ "@types/jest": "^30.0.0",
65
+ "@types/node": "^24.0.15",
66
+ "@types/supertest": "^6.0.3",
67
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
68
+ "@typescript-eslint/parser": "^8.38.0",
69
+ "eslint": "^9.31.0",
70
+ "jest": "^30.0.4",
71
+ "prettier": "^3.6.2",
72
+ "rimraf": "^6.0.1",
73
+ "supertest": "^7.1.3",
74
+ "ts-jest": "^29.4.0",
75
+ "ts-node": "^10.9.2",
76
+ "typescript": "^5.8.3"
77
+ },
78
+ "peerDependencies": {
79
+ "@prisma/client": "^6.12.0",
80
+ "prisma": "^6.12.0"
81
+ }
82
+ }
@@ -0,0 +1,27 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function copyDir(src, dest) {
5
+ if (!fs.existsSync(dest)) {
6
+ fs.mkdirSync(dest, { recursive: true });
7
+ }
8
+
9
+ const entries = fs.readdirSync(src, { withFileTypes: true });
10
+
11
+ for (const entry of entries) {
12
+ const srcPath = path.join(src, entry.name);
13
+ const destPath = path.join(dest, entry.name);
14
+
15
+ if (entry.isDirectory()) {
16
+ copyDir(srcPath, destPath);
17
+ } else {
18
+ fs.copyFileSync(srcPath, destPath);
19
+ }
20
+ }
21
+ }
22
+
23
+ // Copy templates
24
+ copyDir('templates', 'dist/templates');
25
+ copyDir('scripts', 'dist/scripts');
26
+
27
+ console.log('✅ Assets copied to dist/');
@@ -0,0 +1,14 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const templatePath = path.join(__dirname, '..', 'templates', 'schema.prisma');
5
+ const targetPath = path.join(process.cwd(), 'prisma', 'schema.prisma');
6
+
7
+ // Only copy if prisma directory doesn't exist
8
+ if (!fs.existsSync(path.dirname(targetPath))) {
9
+ console.log('📋 Creating default Prisma schema...');
10
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
11
+ fs.copyFileSync(templatePath, targetPath);
12
+ console.log('✅ Default schema.prisma created in prisma/schema.prisma');
13
+ console.log('🔧 Don\'t forget to set your DATABASE_URL in .env file');
14
+ }
@@ -0,0 +1,22 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client-js"
6
+ }
7
+
8
+ datasource db {
9
+ provider = "sqlite"
10
+ url = env("DATABASE_URL")
11
+ }
12
+
13
+ // Add your models here
14
+ // Example:
15
+ // model User {
16
+ // id String @id @default(uuid())
17
+ // name String
18
+ // email String @unique
19
+ // password String
20
+ // createdAt DateTime @default(now())
21
+ // updatedAt DateTime @updatedAt
22
+ // }