crudora 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +554 -328
  3. package/dist/cli.js +72 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/core/crudora.d.ts +34 -9
  6. package/dist/core/crudora.d.ts.map +1 -1
  7. package/dist/core/crudora.js +254 -105
  8. package/dist/core/crudora.js.map +1 -1
  9. package/dist/core/crudoraServer.d.ts +64 -10
  10. package/dist/core/crudoraServer.d.ts.map +1 -1
  11. package/dist/core/crudoraServer.js +138 -19
  12. package/dist/core/crudoraServer.js.map +1 -1
  13. package/dist/core/drizzleTableBuilder.d.ts +6 -0
  14. package/dist/core/drizzleTableBuilder.d.ts.map +1 -0
  15. package/dist/core/drizzleTableBuilder.js +175 -0
  16. package/dist/core/drizzleTableBuilder.js.map +1 -0
  17. package/dist/core/model.d.ts +28 -9
  18. package/dist/core/model.d.ts.map +1 -1
  19. package/dist/core/model.js +33 -70
  20. package/dist/core/model.js.map +1 -1
  21. package/dist/core/repository.d.ts +98 -14
  22. package/dist/core/repository.d.ts.map +1 -1
  23. package/dist/core/repository.js +561 -103
  24. package/dist/core/repository.js.map +1 -1
  25. package/dist/core/schemaGenerator.d.ts +3 -3
  26. package/dist/core/schemaGenerator.d.ts.map +1 -1
  27. package/dist/core/schemaGenerator.js +237 -32
  28. package/dist/core/schemaGenerator.js.map +1 -1
  29. package/dist/decorators/model.d.ts +56 -1
  30. package/dist/decorators/model.d.ts.map +1 -1
  31. package/dist/decorators/model.js +92 -0
  32. package/dist/decorators/model.js.map +1 -1
  33. package/dist/index.d.ts +7 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +12 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/scripts/copy-assets.js +47 -47
  38. package/dist/scripts/postinstall.js +172 -136
  39. package/dist/templates/.env.example +13 -9
  40. package/dist/templates/drizzle.config.ts +10 -0
  41. package/dist/templates/schema.ts +23 -0
  42. package/dist/types/logger.type.d.ts +7 -0
  43. package/dist/types/logger.type.d.ts.map +1 -0
  44. package/dist/types/logger.type.js +3 -0
  45. package/dist/types/logger.type.js.map +1 -0
  46. package/dist/types/model.type.d.ts +30 -5
  47. package/dist/types/model.type.d.ts.map +1 -1
  48. package/dist/utils/validation.d.ts.map +1 -1
  49. package/dist/utils/validation.js +91 -19
  50. package/dist/utils/validation.js.map +1 -1
  51. package/package.json +108 -94
  52. package/scripts/copy-assets.js +47 -47
  53. package/scripts/postinstall.js +172 -136
  54. package/templates/.env.example +13 -9
  55. package/templates/drizzle.config.ts +10 -0
  56. package/templates/schema.ts +23 -0
  57. package/dist/templates/schema.prisma +0 -22
  58. package/templates/schema.prisma +0 -22
@@ -1,136 +1,172 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
-
4
- // Paths
5
- const templatePath = path.join(__dirname, '..', 'templates', 'schema.prisma');
6
- const targetPrismaPath = path.join(process.cwd(), 'prisma', 'schema.prisma');
7
- const targetEnvPath = path.join(process.cwd(), '.env');
8
- const targetServerPath = path.join(process.cwd(), 'src', 'server.ts');
9
- const targetPackagePath = path.join(process.cwd(), 'package.json');
10
-
11
- console.log('šŸš€ Setting up Crudora project...');
12
-
13
- // 1. Create prisma directory and schema
14
- if (!fs.existsSync(path.dirname(targetPrismaPath))) {
15
- console.log('šŸ“‹ Creating Prisma schema...');
16
- fs.mkdirSync(path.dirname(targetPrismaPath), { recursive: true });
17
- fs.copyFileSync(templatePath, targetPrismaPath);
18
- console.log('āœ… Prisma schema created at prisma/schema.prisma');
19
- } else {
20
- console.log('šŸ“‹ Prisma directory already exists, skipping schema creation');
21
- }
22
-
23
- // 2. Create .env file
24
- if (!fs.existsSync(targetEnvPath)) {
25
- console.log('šŸ”§ Creating .env file...');
26
- const envContent = `# Database
27
- DATABASE_URL="file:./dev.db"
28
-
29
- # Server
30
- PORT=3000
31
- NODE_ENV=development
32
-
33
- # API
34
- API_BASE_PATH="/api"
35
- `;
36
- fs.writeFileSync(targetEnvPath, envContent);
37
- console.log('āœ… .env file created');
38
- } else {
39
- console.log('šŸ”§ .env file already exists, skipping creation');
40
- }
41
-
42
- // 3. Create basic server setup
43
- if (!fs.existsSync(targetServerPath)) {
44
- console.log('šŸ–„ļø Creating server setup...');
45
- const serverContent = `const { CrudoraServer } = require('crudora');
46
- const { PrismaClient } = require('@prisma/client');
47
- require('dotenv').config();
48
-
49
- const prisma = new PrismaClient();
50
-
51
- // Example User model (uncomment and modify as needed)
52
- /*
53
- class User {
54
- static tableName = 'users';
55
- static primaryKey = 'id';
56
- static timestamps = true;
57
- static fillable = ['name', 'email'];
58
- static hidden = ['password'];
59
- }
60
- */
61
-
62
- const server = new CrudoraServer({
63
- port: process.env.PORT || 3000,
64
- prisma: prisma,
65
- cors: true,
66
- basePath: process.env.API_BASE_PATH || '/api'
67
- });
68
-
69
- // Register your models here
70
- // server.registerModel(User);
71
-
72
- // Add custom routes if needed
73
- server.get('/health', (req, res) => {
74
- res.json({ status: 'ok', timestamp: new Date() });
75
- });
76
-
77
- // Generate routes and start server
78
- server
79
- .generateRoutes()
80
- .listen(() => {
81
- console.log('šŸš€ Crudora server is running!');
82
- console.log(\`šŸ“š API documentation: http://localhost:\${process.env.PORT || 3000}\${process.env.API_BASE_PATH || '/api'}\`);
83
- });
84
- `;
85
- fs.writeFileSync(targetServerPath, serverContent);
86
- console.log('āœ… Server setup created at server.ts');
87
- } else {
88
- console.log('šŸ–„ļø server.ts already exists, skipping creation');
89
- }
90
-
91
- // 4. Update package.json scripts (if package.json exists)
92
- if (fs.existsSync(targetPackagePath)) {
93
- try {
94
- const packageJson = JSON.parse(fs.readFileSync(targetPackagePath, 'utf8'));
95
-
96
- if (!packageJson.scripts) {
97
- packageJson.scripts = {};
98
- }
99
-
100
- // Add useful scripts if they don't exist
101
- const scriptsToAdd = {
102
- 'build': 'tsc',
103
- 'dev': 'ts-node src/server.ts',
104
- 'start': 'ts-node src/server.ts',
105
- 'start:prod': 'node dist/index.js',
106
- 'db:generate': 'prisma generate',
107
- 'db:push': 'prisma db push',
108
- 'db:migrate': 'prisma migrate dev',
109
- 'db:studio': 'prisma studio'
110
- };
111
-
112
- let scriptsAdded = false;
113
- for (const [scriptName, scriptCommand] of Object.entries(scriptsToAdd)) {
114
- if (!packageJson.scripts[scriptName]) {
115
- packageJson.scripts[scriptName] = scriptCommand;
116
- scriptsAdded = true;
117
- }
118
- }
119
-
120
- if (scriptsAdded) {
121
- fs.writeFileSync(targetPackagePath, JSON.stringify(packageJson, null, 2));
122
- console.log('āœ… Package.json scripts updated');
123
- }
124
- } catch (error) {
125
- console.log('āš ļø Could not update package.json scripts:', error.message);
126
- }
127
- }
128
-
129
- console.log('\nšŸŽ‰ Crudora setup complete!');
130
- console.log('\nšŸ“ Next steps:');
131
- console.log('1. Install dependencies: npm install @prisma/client prisma dotenv');
132
- console.log('2. Generate Prisma client: npm run db:generate');
133
- console.log('3. Push database schema: npm run db:push');
134
- console.log('4. Define your models in server.js');
135
- console.log('5. Start development server: npm run dev');
136
- console.log('\nšŸ“– Documentation: https://github.com/suryamsj/crudora#readme');
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ // ─── Skip guards ──────────────────────────────────────────────────────────────
9
+ // Opt-out: set CRUDORA_SKIP_POSTINSTALL=1 in CI pipelines or Docker builds.
10
+ if (process.env.CRUDORA_SKIP_POSTINSTALL) {
11
+ process.exit(0);
12
+ }
13
+
14
+ // Many CI systems set CI=true — don't scaffold files into a CI workspace.
15
+ if (process.env.CI) {
16
+ process.exit(0);
17
+ }
18
+
19
+ // Running inside node_modules means someone else is installing crudora as a dep.
20
+ // Scaffold into their project root (process.cwd()), not the package directory.
21
+ // Guard: if there's no package.json in cwd, we're probably not in a real project.
22
+ const cwdPkgPath = path.join(process.cwd(), 'package.json');
23
+ if (!fs.existsSync(cwdPkgPath)) {
24
+ process.exit(0);
25
+ }
26
+
27
+ // ─── Peer dependency check ────────────────────────────────────────────────────
28
+ try {
29
+ const cwdPkg = JSON.parse(fs.readFileSync(cwdPkgPath, 'utf-8'));
30
+ const hasDrizzle =
31
+ cwdPkg.dependencies?.['drizzle-orm'] ||
32
+ cwdPkg.devDependencies?.['drizzle-orm'];
33
+ if (!hasDrizzle) {
34
+ console.warn(
35
+ '\nāš ļø Crudora: drizzle-orm is not listed in your dependencies.\n' +
36
+ ' Run: npm install drizzle-orm\n' +
37
+ ' Also install the driver for your database:\n' +
38
+ ' PostgreSQL: npm install pg\n' +
39
+ ' MySQL: npm install mysql2\n',
40
+ );
41
+ }
42
+ } catch {
43
+ // Non-fatal — package.json may not be JSON-parseable
44
+ }
45
+
46
+ const templateDir = path.join(__dirname, '..', 'templates');
47
+ const targetEnvPath = path.join(process.cwd(), '.env');
48
+ const targetServerPath = path.join(process.cwd(), 'src', 'server.ts');
49
+ const targetDrizzleConfig = path.join(process.cwd(), 'drizzle.config.ts');
50
+ const targetSchemaDir = path.join(process.cwd(), 'src', 'db');
51
+ const targetSchemaPath = path.join(targetSchemaDir, 'schema.ts');
52
+
53
+ console.log('šŸš€ Setting up Crudora project...');
54
+
55
+ // 1. Create .env file
56
+ if (!fs.existsSync(targetEnvPath)) {
57
+ console.log('šŸ”§ Creating .env file...');
58
+ const envContent = `# Database — choose one based on your dialect
59
+ # PostgreSQL
60
+ DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
61
+
62
+ # MySQL (uncomment if using MySQL)
63
+ # DATABASE_URL="mysql://user:password@localhost:3306/mydb"
64
+
65
+ # Server
66
+ PORT=3000
67
+ NODE_ENV=development
68
+
69
+ # API
70
+ API_BASE_PATH="/api"
71
+ `;
72
+ fs.writeFileSync(targetEnvPath, envContent);
73
+ console.log('āœ… .env file created');
74
+ } else {
75
+ console.log('šŸ”§ .env file already exists, skipping creation');
76
+ }
77
+
78
+ // 2. Create drizzle.config.ts
79
+ if (!fs.existsSync(targetDrizzleConfig)) {
80
+ console.log('šŸ“‹ Creating drizzle.config.ts...');
81
+ fs.copyFileSync(path.join(templateDir, 'drizzle.config.ts'), targetDrizzleConfig);
82
+ console.log('āœ… drizzle.config.ts created');
83
+ } else {
84
+ console.log('šŸ“‹ drizzle.config.ts already exists, skipping');
85
+ }
86
+
87
+ // 3. Create src/db/schema.ts
88
+ if (!fs.existsSync(targetSchemaPath)) {
89
+ console.log('šŸ“‹ Creating src/db/schema.ts...');
90
+ if (!fs.existsSync(targetSchemaDir)) {
91
+ fs.mkdirSync(targetSchemaDir, { recursive: true });
92
+ }
93
+ fs.copyFileSync(path.join(templateDir, 'schema.ts'), targetSchemaPath);
94
+ console.log('āœ… src/db/schema.ts created');
95
+ } else {
96
+ console.log('šŸ“‹ src/db/schema.ts already exists, skipping');
97
+ }
98
+
99
+ // 4. Create basic server setup
100
+ if (!fs.existsSync(targetServerPath)) {
101
+ console.log('šŸ–„ļø Creating server setup...');
102
+ const serverContent = `import { CrudoraServer, Model, Field } from 'crudora';
103
+ import { drizzle } from 'drizzle-orm/node-postgres';
104
+ import { Pool } from 'pg';
105
+ import 'dotenv/config';
106
+
107
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
108
+ const db = drizzle(pool);
109
+
110
+ // Example User model (uncomment and modify as needed)
111
+ /*
112
+ class User extends Model {
113
+ static schema = 'auth'; // optional: database schema
114
+ static tableName = 'users';
115
+ static hidden = ['password'];
116
+
117
+ @Field({ type: 'uuid', primary: true })
118
+ id!: string;
119
+
120
+ @Field({ type: 'string', required: true, unique: true })
121
+ email!: string;
122
+
123
+ @Field({ type: 'string', required: true })
124
+ password!: string;
125
+ }
126
+ */
127
+
128
+ const server = new CrudoraServer({
129
+ port: Number(process.env.PORT) || 3000,
130
+ db,
131
+ dialect: 'postgresql',
132
+ cors: true,
133
+ basePath: process.env.API_BASE_PATH || '/api',
134
+ });
135
+
136
+ // Register your models here
137
+ // server.registerModel(User);
138
+
139
+ server.get('/health', (_req, res) => {
140
+ res.json({ success: true, data: { status: 'ok', timestamp: new Date() } });
141
+ });
142
+
143
+ server
144
+ .generateRoutes()
145
+ .listen(() => {
146
+ console.log('šŸš€ Crudora server is running!');
147
+ });
148
+ `;
149
+ if (!fs.existsSync(path.dirname(targetServerPath))) {
150
+ fs.mkdirSync(path.dirname(targetServerPath), { recursive: true });
151
+ }
152
+ fs.writeFileSync(targetServerPath, serverContent);
153
+ console.log('āœ… Server setup created at src/server.ts');
154
+ } else {
155
+ console.log('šŸ–„ļø src/server.ts already exists, skipping creation');
156
+ }
157
+
158
+ console.log('\nšŸŽ‰ Crudora setup complete!');
159
+ console.log('\nšŸ“ Next steps:');
160
+ console.log('1. Install dependencies: npm install drizzle-orm pg');
161
+ console.log('2. Update DATABASE_URL in .env');
162
+ console.log('3. Define your models in src/server.ts');
163
+ console.log('4. Add these scripts to your package.json:');
164
+ console.log(' "dev": "ts-node src/server.ts"');
165
+ console.log(' "build": "tsc"');
166
+ console.log(' "db:generate": "drizzle-kit generate"');
167
+ console.log(' "db:push": "drizzle-kit push"');
168
+ console.log(' "db:migrate": "drizzle-kit migrate"');
169
+ console.log(' "db:studio": "drizzle-kit studio"');
170
+ console.log('5. Push schema to DB: npx drizzle-kit push');
171
+ console.log('6. Start server: npx ts-node src/server.ts');
172
+ console.log('\nšŸ“– Documentation: https://github.com/suryamsj/crudora#readme');
@@ -1,9 +1,13 @@
1
- # Database
2
- DATABASE_URL="file:./dev.db"
3
-
4
- # Server
5
- PORT=3000
6
- NODE_ENV=development
7
-
8
- # API
9
- API_BASE_PATH="/api"
1
+ # Database — choose one based on your dialect
2
+ # PostgreSQL
3
+ DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
4
+
5
+ # MySQL (uncomment if using MySQL)
6
+ # DATABASE_URL="mysql://user:password@localhost:3306/mydb"
7
+
8
+ # Server
9
+ PORT=3000
10
+ NODE_ENV=development
11
+
12
+ # API
13
+ API_BASE_PATH="/api"
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'drizzle-kit';
2
+
3
+ export default defineConfig({
4
+ schema: './src/db/schema.ts',
5
+ out: './drizzle',
6
+ dialect: 'postgresql', // or 'mysql'
7
+ dbCredentials: {
8
+ url: process.env.DATABASE_URL!,
9
+ },
10
+ });
@@ -0,0 +1,23 @@
1
+ // Auto-generated by Crudora — do not edit manually
2
+ // Run: npx crudora generate-schema > src/db/schema.ts
3
+ //
4
+ // Example schema with multiple PostgreSQL schemas:
5
+ //
6
+ // import { pgTable, pgSchema, uuid, varchar, timestamp } from 'drizzle-orm/pg-core';
7
+ //
8
+ // const authSchema = pgSchema('auth');
9
+ //
10
+ // export const usersTable = authSchema.table('users', {
11
+ // id: uuid('id').primaryKey(),
12
+ // email: varchar('email', { length: 255 }).notNull().unique(),
13
+ // password: varchar('password', { length: 255 }).notNull(),
14
+ // createdAt: timestamp('createdAt', { mode: 'date' }).defaultNow().notNull(),
15
+ // updatedAt: timestamp('updatedAt', { mode: 'date' }).defaultNow().notNull(),
16
+ // });
17
+ //
18
+ // export const postsTable = pgTable('posts', {
19
+ // id: uuid('id').primaryKey(),
20
+ // title: varchar('title', { length: 255 }).notNull(),
21
+ // createdAt: timestamp('createdAt', { mode: 'date' }).defaultNow().notNull(),
22
+ // updatedAt: timestamp('updatedAt', { mode: 'date' }).defaultNow().notNull(),
23
+ // });
@@ -1,22 +0,0 @@
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
- // }
@@ -1,22 +0,0 @@
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
- // }