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.
- package/LICENSE +21 -21
- package/README.md +554 -328
- package/dist/cli.js +72 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/crudora.d.ts +34 -9
- package/dist/core/crudora.d.ts.map +1 -1
- package/dist/core/crudora.js +254 -105
- package/dist/core/crudora.js.map +1 -1
- package/dist/core/crudoraServer.d.ts +64 -10
- package/dist/core/crudoraServer.d.ts.map +1 -1
- package/dist/core/crudoraServer.js +138 -19
- package/dist/core/crudoraServer.js.map +1 -1
- package/dist/core/drizzleTableBuilder.d.ts +6 -0
- package/dist/core/drizzleTableBuilder.d.ts.map +1 -0
- package/dist/core/drizzleTableBuilder.js +175 -0
- package/dist/core/drizzleTableBuilder.js.map +1 -0
- package/dist/core/model.d.ts +28 -9
- package/dist/core/model.d.ts.map +1 -1
- package/dist/core/model.js +33 -70
- package/dist/core/model.js.map +1 -1
- package/dist/core/repository.d.ts +98 -14
- package/dist/core/repository.d.ts.map +1 -1
- package/dist/core/repository.js +561 -103
- package/dist/core/repository.js.map +1 -1
- package/dist/core/schemaGenerator.d.ts +3 -3
- package/dist/core/schemaGenerator.d.ts.map +1 -1
- package/dist/core/schemaGenerator.js +237 -32
- package/dist/core/schemaGenerator.js.map +1 -1
- package/dist/decorators/model.d.ts +56 -1
- package/dist/decorators/model.d.ts.map +1 -1
- package/dist/decorators/model.js +92 -0
- package/dist/decorators/model.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/copy-assets.js +47 -47
- package/dist/scripts/postinstall.js +172 -136
- package/dist/templates/.env.example +13 -9
- package/dist/templates/drizzle.config.ts +10 -0
- package/dist/templates/schema.ts +23 -0
- package/dist/types/logger.type.d.ts +7 -0
- package/dist/types/logger.type.d.ts.map +1 -0
- package/dist/types/logger.type.js +3 -0
- package/dist/types/logger.type.js.map +1 -0
- package/dist/types/model.type.d.ts +30 -5
- package/dist/types/model.type.d.ts.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +91 -19
- package/dist/utils/validation.js.map +1 -1
- package/package.json +108 -94
- package/scripts/copy-assets.js +47 -47
- package/scripts/postinstall.js +172 -136
- package/templates/.env.example +13 -9
- package/templates/drizzle.config.ts +10 -0
- package/templates/schema.ts +23 -0
- package/dist/templates/schema.prisma +0 -22
- package/templates/schema.prisma +0 -22
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Model = exports.ValidationGenerator = exports.SchemaGenerator = exports.Repository = exports.CrudoraServer = exports.Crudora = void 0;
|
|
3
|
+
exports.getRelationMetadata = exports.getFieldMetadata = exports.BelongsToMany = exports.BelongsTo = exports.HasOne = exports.HasMany = exports.Field = exports.Model = exports.ValidationGenerator = exports.DrizzleTableBuilder = exports.SchemaGenerator = exports.NotFoundError = exports.Repository = exports.CrudoraServer = exports.Crudora = void 0;
|
|
4
4
|
require("reflect-metadata");
|
|
5
5
|
var crudora_1 = require("./core/crudora");
|
|
6
6
|
Object.defineProperty(exports, "Crudora", { enumerable: true, get: function () { return crudora_1.Crudora; } });
|
|
@@ -8,10 +8,21 @@ var crudoraServer_1 = require("./core/crudoraServer");
|
|
|
8
8
|
Object.defineProperty(exports, "CrudoraServer", { enumerable: true, get: function () { return crudoraServer_1.CrudoraServer; } });
|
|
9
9
|
var repository_1 = require("./core/repository");
|
|
10
10
|
Object.defineProperty(exports, "Repository", { enumerable: true, get: function () { return repository_1.Repository; } });
|
|
11
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return repository_1.NotFoundError; } });
|
|
11
12
|
var schemaGenerator_1 = require("./core/schemaGenerator");
|
|
12
13
|
Object.defineProperty(exports, "SchemaGenerator", { enumerable: true, get: function () { return schemaGenerator_1.SchemaGenerator; } });
|
|
14
|
+
var drizzleTableBuilder_1 = require("./core/drizzleTableBuilder");
|
|
15
|
+
Object.defineProperty(exports, "DrizzleTableBuilder", { enumerable: true, get: function () { return drizzleTableBuilder_1.DrizzleTableBuilder; } });
|
|
13
16
|
var validation_1 = require("./utils/validation");
|
|
14
17
|
Object.defineProperty(exports, "ValidationGenerator", { enumerable: true, get: function () { return validation_1.ValidationGenerator; } });
|
|
15
18
|
var model_1 = require("./core/model");
|
|
16
19
|
Object.defineProperty(exports, "Model", { enumerable: true, get: function () { return model_1.Model; } });
|
|
20
|
+
var model_2 = require("./decorators/model");
|
|
21
|
+
Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return model_2.Field; } });
|
|
22
|
+
Object.defineProperty(exports, "HasMany", { enumerable: true, get: function () { return model_2.HasMany; } });
|
|
23
|
+
Object.defineProperty(exports, "HasOne", { enumerable: true, get: function () { return model_2.HasOne; } });
|
|
24
|
+
Object.defineProperty(exports, "BelongsTo", { enumerable: true, get: function () { return model_2.BelongsTo; } });
|
|
25
|
+
Object.defineProperty(exports, "BelongsToMany", { enumerable: true, get: function () { return model_2.BelongsToMany; } });
|
|
26
|
+
Object.defineProperty(exports, "getFieldMetadata", { enumerable: true, get: function () { return model_2.getFieldMetadata; } });
|
|
27
|
+
Object.defineProperty(exports, "getRelationMetadata", { enumerable: true, get: function () { return model_2.getRelationMetadata; } });
|
|
17
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4BAA0B;AAC1B,0CAAyC;AAAhC,kGAAA,OAAO,OAAA;AAChB,sDAAqD;AAA5C,8GAAA,aAAa,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4BAA0B;AAC1B,0CAAyC;AAAhC,kGAAA,OAAO,OAAA;AAChB,sDAAqD;AAA5C,8GAAA,aAAa,OAAA;AAEtB,gDAA8D;AAArD,wGAAA,UAAU,OAAA;AAAE,2GAAA,aAAa,OAAA;AAElC,0DAAyD;AAAhD,kHAAA,eAAe,OAAA;AACxB,kEAAiE;AAAxD,0HAAA,mBAAmB,OAAA;AAC5B,iDAAyD;AAAhD,iHAAA,mBAAmB,OAAA;AAC5B,sCAAqC;AAA5B,8FAAA,KAAK,OAAA;AAEd,4CAQ4B;AAP1B,8FAAA,KAAK,OAAA;AACL,gGAAA,OAAO,OAAA;AACP,+FAAA,MAAM,OAAA;AACN,kGAAA,SAAS,OAAA;AACT,sGAAA,aAAa,OAAA;AACb,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA"}
|
|
@@ -1,47 +1,47 @@
|
|
|
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
|
-
function copyDir(src, dest) {
|
|
9
|
-
if (!fs.existsSync(dest)) {
|
|
10
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
14
|
-
|
|
15
|
-
for (const entry of entries) {
|
|
16
|
-
const srcPath = path.join(src, entry.name);
|
|
17
|
-
const destPath = path.join(dest, entry.name);
|
|
18
|
-
|
|
19
|
-
if (entry.isDirectory()) {
|
|
20
|
-
copyDir(srcPath, destPath);
|
|
21
|
-
} else {
|
|
22
|
-
fs.copyFileSync(srcPath, destPath);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Copy templates
|
|
28
|
-
copyDir('templates', 'dist/templates');
|
|
29
|
-
copyDir('scripts', 'dist/scripts');
|
|
30
|
-
|
|
31
|
-
// Make sure bin directory exists
|
|
32
|
-
if (!fs.existsSync('dist/bin')) {
|
|
33
|
-
fs.mkdirSync('dist/bin', { recursive: true });
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Ensure bin file is executable
|
|
37
|
-
if (fs.existsSync('bin/crudora.js')) {
|
|
38
|
-
fs.copyFileSync('bin/crudora.js', 'dist/bin/crudora.js');
|
|
39
|
-
try {
|
|
40
|
-
// Make executable on Unix systems
|
|
41
|
-
fs.chmodSync('dist/bin/crudora.js', '755');
|
|
42
|
-
} catch (error) {
|
|
43
|
-
// Ignore errors on Windows
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
console.log('✅ Assets copied to dist/');
|
|
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
|
+
function copyDir(src, dest) {
|
|
9
|
+
if (!fs.existsSync(dest)) {
|
|
10
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
14
|
+
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const srcPath = path.join(src, entry.name);
|
|
17
|
+
const destPath = path.join(dest, entry.name);
|
|
18
|
+
|
|
19
|
+
if (entry.isDirectory()) {
|
|
20
|
+
copyDir(srcPath, destPath);
|
|
21
|
+
} else {
|
|
22
|
+
fs.copyFileSync(srcPath, destPath);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Copy templates
|
|
28
|
+
copyDir('templates', 'dist/templates');
|
|
29
|
+
copyDir('scripts', 'dist/scripts');
|
|
30
|
+
|
|
31
|
+
// Make sure bin directory exists
|
|
32
|
+
if (!fs.existsSync('dist/bin')) {
|
|
33
|
+
fs.mkdirSync('dist/bin', { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Ensure bin file is executable
|
|
37
|
+
if (fs.existsSync('bin/crudora.js')) {
|
|
38
|
+
fs.copyFileSync('bin/crudora.js', 'dist/bin/crudora.js');
|
|
39
|
+
try {
|
|
40
|
+
// Make executable on Unix systems
|
|
41
|
+
fs.chmodSync('dist/bin/crudora.js', '755');
|
|
42
|
+
} catch (error) {
|
|
43
|
+
// Ignore errors on Windows
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('✅ Assets copied to dist/');
|
|
@@ -1,136 +1,172 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
|
|
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,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
|
+
// });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface CrudoraLogger {
|
|
2
|
+
error(message: string, context?: Record<string, any>): void;
|
|
3
|
+
warn(message: string, context?: Record<string, any>): void;
|
|
4
|
+
info(message: string, context?: Record<string, any>): void;
|
|
5
|
+
debug(message: string, context?: Record<string, any>): void;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=logger.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.type.d.ts","sourceRoot":"","sources":["../../src/types/logger.type.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAC3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.type.js","sourceRoot":"","sources":["../../src/types/logger.type.ts"],"names":[],"mappings":""}
|
|
@@ -1,13 +1,38 @@
|
|
|
1
|
-
export
|
|
2
|
-
tableName?: string;
|
|
3
|
-
timestamps?: boolean;
|
|
4
|
-
}
|
|
1
|
+
export type FieldType = 'string' | 'text' | 'integer' | 'number' | 'boolean' | 'date' | 'uuid' | 'decimal' | 'json' | 'enum' | 'bigint' | 'serial' | 'array';
|
|
5
2
|
export interface FieldOptions {
|
|
6
|
-
type:
|
|
3
|
+
type: FieldType;
|
|
7
4
|
required?: boolean;
|
|
8
5
|
unique?: boolean;
|
|
9
6
|
default?: any;
|
|
10
7
|
length?: number;
|
|
11
8
|
primary?: boolean;
|
|
9
|
+
nullable?: boolean;
|
|
10
|
+
precision?: number;
|
|
11
|
+
scale?: number;
|
|
12
|
+
/** Required when type is 'enum'. Lists the allowed values. */
|
|
13
|
+
enumValues?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface ModelOptions {
|
|
16
|
+
tableName?: string;
|
|
17
|
+
timestamps?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export type Dialect = 'postgresql' | 'mysql';
|
|
20
|
+
export type RelationType = 'hasOne' | 'hasMany' | 'belongsTo' | 'belongsToMany';
|
|
21
|
+
export interface RelationDefinition {
|
|
22
|
+
type: RelationType;
|
|
23
|
+
/** Lazy model getter — avoids circular-import issues */
|
|
24
|
+
model: () => any;
|
|
25
|
+
/** The foreign-key column name */
|
|
26
|
+
foreignKey: string;
|
|
27
|
+
/**
|
|
28
|
+
* hasOne / hasMany: column on the owning (local) side. Defaults to the model's primary key.
|
|
29
|
+
* belongsTo : column on the related side (the "owner"). Defaults to the related model's primary key.
|
|
30
|
+
* belongsToMany: override for this model's local key (defaults to primary key).
|
|
31
|
+
*/
|
|
32
|
+
relatedKey?: string;
|
|
33
|
+
/** Lazy getter returning the pivot/junction model constructor. */
|
|
34
|
+
pivotModel?: () => any;
|
|
35
|
+
/** Column on the pivot table that points to the **related** model. */
|
|
36
|
+
pivotRelatedKey?: string;
|
|
12
37
|
}
|
|
13
38
|
//# sourceMappingURL=model.type.d.ts.map
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"model.type.d.ts","sourceRoot":"","sources":["../../src/types/model.type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,MAAM,GACN,SAAS,GACT,QAAQ,GACR,SAAS,GACT,MAAM,GACN,MAAM,GACN,SAAS,GACT,MAAM,GACN,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,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;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,OAAO,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,wDAAwD;IACxD,KAAK,EAAE,MAAM,GAAG,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,GAAG,CAAC;IACvB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AA4FxD,qBAAa,mBAAmB;IAC9B,MAAM,CAAC,iBAAiB,CAAC,CAAC,SAAS,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAWjG,MAAM,CAAC,uBAAuB,CAAC,CAAC,SAAS,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;CAUjG"}
|