outlet-orm 3.2.0 → 4.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/README.md +114 -1
- package/bin/init.js +31 -0
- package/package.json +4 -2
- package/src/Model.js +1 -1
- package/types/index.d.ts +298 -20
package/README.md
CHANGED
|
@@ -28,6 +28,61 @@ Outlet ORM utilise des peerDependencies optionnelles pour les drivers de base de
|
|
|
28
28
|
|
|
29
29
|
Si aucun driver n'est installé, un message d'erreur explicite vous indiquera lequel installer lors de la connexion.
|
|
30
30
|
|
|
31
|
+
## 📁 Structure de Projet Recommandée
|
|
32
|
+
|
|
33
|
+
Organisez votre projet utilisant Outlet ORM comme suit :
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
mon-projet/
|
|
37
|
+
├── .env # Configuration de la base de données
|
|
38
|
+
├── package.json
|
|
39
|
+
├── database/
|
|
40
|
+
│ ├── config.js # Config migrations (généré par outlet-init)
|
|
41
|
+
│ └── migrations/ # Vos fichiers de migration
|
|
42
|
+
│ ├── 20240101_create_users_table.js
|
|
43
|
+
│ └── 20240102_create_posts_table.js
|
|
44
|
+
├── models/ # Vos classes Model
|
|
45
|
+
│ ├── User.js
|
|
46
|
+
│ ├── Post.js
|
|
47
|
+
│ └── Comment.js
|
|
48
|
+
├── controllers/ # Vos contrôleurs (logique métier)
|
|
49
|
+
│ ├── UserController.js
|
|
50
|
+
│ ├── PostController.js
|
|
51
|
+
│ └── CommentController.js
|
|
52
|
+
├── routes/ # Vos fichiers de routes
|
|
53
|
+
│ ├── index.js
|
|
54
|
+
│ ├── userRoutes.js
|
|
55
|
+
│ └── postRoutes.js
|
|
56
|
+
├── middlewares/ # Vos middlewares
|
|
57
|
+
│ ├── auth.js
|
|
58
|
+
│ └── validation.js
|
|
59
|
+
├── services/ # Vos services (logique réutilisable)
|
|
60
|
+
│ ├── AuthService.js
|
|
61
|
+
│ └── EmailService.js
|
|
62
|
+
├── assets/ # Ressources statiques
|
|
63
|
+
│ ├── images/ # Images (png, jpg, svg...)
|
|
64
|
+
│ ├── videos/ # Fichiers vidéo
|
|
65
|
+
│ ├── icons/ # Icônes
|
|
66
|
+
│ ├── fonts/ # Polices personnalisées
|
|
67
|
+
│ ├── css/ # Feuilles de style
|
|
68
|
+
│ └── js/ # Scripts front-end
|
|
69
|
+
├── src/ # Votre code applicatif
|
|
70
|
+
│ └── index.js
|
|
71
|
+
└── tests/ # Vos tests
|
|
72
|
+
└── models.test.js
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Dossier | Rôle | Créé par |
|
|
76
|
+
|---------|------|----------|
|
|
77
|
+
| `database/config.js` | Configuration des migrations | `outlet-init` |
|
|
78
|
+
| `database/migrations/` | Fichiers de migration | `outlet-migrate make` |
|
|
79
|
+
| `models/` | Vos classes Model | Vous (recommandé) |
|
|
80
|
+
| `controllers/` | Vos contrôleurs (logique métier) | Vous (recommandé) |
|
|
81
|
+
| `routes/` | Définition des routes API/Web | Vous (recommandé) |
|
|
82
|
+
| `middlewares/` | Middlewares d'authentification, validation, etc. | Vous (recommandé) |
|
|
83
|
+
| `services/` | Services réutilisables (email, auth, etc.) | Vous (recommandé) |
|
|
84
|
+
| `assets/` | Ressources statiques (images, vidéos, icônes, fonts, css, js) | Vous (recommandé) |
|
|
85
|
+
|
|
31
86
|
## ✨ Fonctionnalités clés
|
|
32
87
|
|
|
33
88
|
- **API inspirée d'Eloquent** (Active Record) pour un usage fluide
|
|
@@ -56,7 +111,7 @@ Si aucun driver n'est installé, un message d'erreur explicite vous indiquera le
|
|
|
56
111
|
- **CLI pratiques**: `outlet-init`, `outlet-migrate`, `outlet-convert`
|
|
57
112
|
- **Configuration via `.env`** (chargée automatiquement)
|
|
58
113
|
- **Multi-base de données**: MySQL, PostgreSQL et SQLite
|
|
59
|
-
- **Types TypeScript**
|
|
114
|
+
- **Types TypeScript complets** avec Generic Model et Schema Builder typé (v4.0.0+)
|
|
60
115
|
|
|
61
116
|
## ⚡ Démarrage Rapide
|
|
62
117
|
|
|
@@ -1070,6 +1125,64 @@ outlet-convert
|
|
|
1070
1125
|
- [Détection des Relations](docs/RELATIONS_DETECTION.md)
|
|
1071
1126
|
- [Guide de démarrage rapide](docs/QUICKSTART.md)
|
|
1072
1127
|
- [Architecture](docs/ARCHITECTURE.md)
|
|
1128
|
+
- [**TypeScript (complet)**](docs/TYPESCRIPT.md)
|
|
1129
|
+
|
|
1130
|
+
## 📘 TypeScript Support
|
|
1131
|
+
|
|
1132
|
+
Outlet ORM v4.0.0 inclut des définitions TypeScript complètes avec support des **generics pour les attributs typés**.
|
|
1133
|
+
|
|
1134
|
+
### Modèles typés
|
|
1135
|
+
|
|
1136
|
+
```typescript
|
|
1137
|
+
import { Model, HasManyRelation } from 'outlet-orm';
|
|
1138
|
+
|
|
1139
|
+
interface UserAttributes {
|
|
1140
|
+
id: number;
|
|
1141
|
+
name: string;
|
|
1142
|
+
email: string;
|
|
1143
|
+
role: 'admin' | 'user';
|
|
1144
|
+
created_at: Date;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
class User extends Model<UserAttributes> {
|
|
1148
|
+
static table = 'users';
|
|
1149
|
+
static fillable = ['name', 'email', 'role'];
|
|
1150
|
+
|
|
1151
|
+
posts(): HasManyRelation<Post> {
|
|
1152
|
+
return this.hasMany(Post, 'user_id');
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// Type-safe getAttribute/setAttribute
|
|
1157
|
+
const user = await User.find(1);
|
|
1158
|
+
const name: string = user.getAttribute('name'); // ✅ Type inféré
|
|
1159
|
+
const role: 'admin' | 'user' = user.getAttribute('role');
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
### Migrations typées
|
|
1163
|
+
|
|
1164
|
+
```typescript
|
|
1165
|
+
import { MigrationInterface, Schema, TableBuilder } from 'outlet-orm';
|
|
1166
|
+
|
|
1167
|
+
export const migration: MigrationInterface = {
|
|
1168
|
+
name: 'create_users_table',
|
|
1169
|
+
|
|
1170
|
+
async up(): Promise<void> {
|
|
1171
|
+
await Schema.create('users', (table: TableBuilder) => {
|
|
1172
|
+
table.id();
|
|
1173
|
+
table.string('name');
|
|
1174
|
+
table.string('email').unique();
|
|
1175
|
+
table.timestamps();
|
|
1176
|
+
});
|
|
1177
|
+
},
|
|
1178
|
+
|
|
1179
|
+
async down(): Promise<void> {
|
|
1180
|
+
await Schema.dropIfExists('users');
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
📖 [Guide TypeScript complet](docs/TYPESCRIPT.md)
|
|
1073
1186
|
|
|
1074
1187
|
## 🤝 Contribution
|
|
1075
1188
|
|
package/bin/init.js
CHANGED
|
@@ -93,6 +93,37 @@ module.exports = db;
|
|
|
93
93
|
fs.writeFileSync(configPath, configContent);
|
|
94
94
|
console.log(`\n✅ Fichier de configuration créé: ${configPath}`);
|
|
95
95
|
|
|
96
|
+
// Create project structure directories
|
|
97
|
+
const directories = [
|
|
98
|
+
'database',
|
|
99
|
+
'database/migrations',
|
|
100
|
+
'models',
|
|
101
|
+
'controllers',
|
|
102
|
+
'routes',
|
|
103
|
+
'middlewares',
|
|
104
|
+
'services',
|
|
105
|
+
'assets',
|
|
106
|
+
'assets/images',
|
|
107
|
+
'assets/videos',
|
|
108
|
+
'assets/icons',
|
|
109
|
+
'assets/fonts',
|
|
110
|
+
'assets/css',
|
|
111
|
+
'assets/js',
|
|
112
|
+
'src',
|
|
113
|
+
'tests'
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
console.log('\n📁 Création de la structure de projet...');
|
|
117
|
+
for (const dir of directories) {
|
|
118
|
+
const dirPath = path.join(process.cwd(), dir);
|
|
119
|
+
if (!fs.existsSync(dirPath)) {
|
|
120
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
121
|
+
console.log(` ✅ ${dir}/`);
|
|
122
|
+
} else {
|
|
123
|
+
console.log(` ⏭️ ${dir}/ (existe déjà)`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
96
127
|
// Generate example model
|
|
97
128
|
const modelContent = `const { Model } = require('outlet-orm');
|
|
98
129
|
const db = require('./database');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "outlet-orm",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "A Laravel Eloquent-inspired ORM for Node.js with support for MySQL, PostgreSQL, and SQLite",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -66,8 +66,10 @@
|
|
|
66
66
|
"sqlite3": { "optional": true }
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
+
"@types/node": "^20.10.0",
|
|
69
70
|
"eslint": "^8.50.0",
|
|
70
|
-
"jest": "^29.7.0"
|
|
71
|
+
"jest": "^29.7.0",
|
|
72
|
+
"typescript": "^5.3.0"
|
|
71
73
|
},
|
|
72
74
|
"engines": {
|
|
73
75
|
"node": ">=18.0.0"
|
package/src/Model.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -2,6 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
declare module 'outlet-orm' {
|
|
4
4
|
|
|
5
|
+
// ==================== Type Utilities ====================
|
|
6
|
+
|
|
7
|
+
/** Event names for Model lifecycle hooks */
|
|
8
|
+
export type ModelEventName =
|
|
9
|
+
| 'creating' | 'created'
|
|
10
|
+
| 'updating' | 'updated'
|
|
11
|
+
| 'saving' | 'saved'
|
|
12
|
+
| 'deleting' | 'deleted'
|
|
13
|
+
| 'restoring' | 'restored';
|
|
14
|
+
|
|
15
|
+
/** SQL WHERE operators */
|
|
16
|
+
export type WhereOperator =
|
|
17
|
+
| '=' | '!=' | '<>'
|
|
18
|
+
| '>' | '>=' | '<' | '<='
|
|
19
|
+
| 'LIKE' | 'NOT LIKE' | 'like' | 'not like'
|
|
20
|
+
| 'IN' | 'NOT IN' | 'in' | 'not in'
|
|
21
|
+
| 'BETWEEN' | 'NOT BETWEEN'
|
|
22
|
+
| 'IS NULL' | 'IS NOT NULL';
|
|
23
|
+
|
|
24
|
+
/** Base attributes every model has */
|
|
25
|
+
export interface BaseModelAttributes {
|
|
26
|
+
id?: number | string;
|
|
27
|
+
created_at?: Date | string;
|
|
28
|
+
updated_at?: Date | string;
|
|
29
|
+
deleted_at?: Date | string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Insert operation result */
|
|
33
|
+
export interface InsertResult {
|
|
34
|
+
insertId: number | string;
|
|
35
|
+
affectedRows: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Update operation result */
|
|
39
|
+
export interface UpdateResult {
|
|
40
|
+
affectedRows: number;
|
|
41
|
+
changedRows?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Delete operation result */
|
|
45
|
+
export interface DeleteResult {
|
|
46
|
+
affectedRows: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
5
49
|
// ==================== Database Connection ====================
|
|
6
50
|
|
|
7
51
|
export interface DatabaseConfig {
|
|
@@ -39,18 +83,18 @@ declare module 'outlet-orm' {
|
|
|
39
83
|
static isLogging(): boolean;
|
|
40
84
|
|
|
41
85
|
select(table: string, query: QueryObject): Promise<any[]>;
|
|
42
|
-
insert(table: string, data: Record<string, any>): Promise<
|
|
86
|
+
insert(table: string, data: Record<string, any>): Promise<InsertResult>;
|
|
43
87
|
insertMany(table: string, data: Record<string, any>[]): Promise<{ affectedRows: number }>;
|
|
44
|
-
update(table: string, data: Record<string, any>, query: QueryObject): Promise<
|
|
45
|
-
delete(table: string, query: QueryObject): Promise<
|
|
88
|
+
update(table: string, data: Record<string, any>, query: QueryObject): Promise<UpdateResult>;
|
|
89
|
+
delete(table: string, query: QueryObject): Promise<DeleteResult>;
|
|
46
90
|
count(table: string, query: QueryObject): Promise<number>;
|
|
47
91
|
executeRawQuery(sql: string, params?: any[]): Promise<any[]>;
|
|
48
92
|
/** Execute raw SQL and return driver-native results (used by migrations) */
|
|
49
93
|
execute(sql: string, params?: any[]): Promise<any>;
|
|
50
94
|
/** Atomically increment a column respecting query wheres */
|
|
51
|
-
increment(table: string, column: string, query: QueryObject, amount?: number): Promise<
|
|
95
|
+
increment(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
|
|
52
96
|
/** Atomically decrement a column respecting query wheres */
|
|
53
|
-
decrement(table: string, column: string, query: QueryObject, amount?: number): Promise<
|
|
97
|
+
decrement(table: string, column: string, query: QueryObject, amount?: number): Promise<UpdateResult>;
|
|
54
98
|
close(): Promise<void>;
|
|
55
99
|
/** Backwards-compatible alias used by CLI */
|
|
56
100
|
disconnect(): Promise<void>;
|
|
@@ -72,7 +116,7 @@ declare module 'outlet-orm' {
|
|
|
72
116
|
|
|
73
117
|
export interface WhereClause {
|
|
74
118
|
column?: string;
|
|
75
|
-
operator?: string;
|
|
119
|
+
operator?: WhereOperator | string;
|
|
76
120
|
value?: any;
|
|
77
121
|
values?: any[];
|
|
78
122
|
type: 'basic' | 'in' | 'notIn' | 'null' | 'notNull' | 'between' | 'like';
|
|
@@ -178,7 +222,32 @@ declare module 'outlet-orm' {
|
|
|
178
222
|
|
|
179
223
|
export type CastType = 'int' | 'integer' | 'float' | 'double' | 'string' | 'bool' | 'boolean' | 'array' | 'json' | 'date' | 'datetime' | 'timestamp';
|
|
180
224
|
|
|
181
|
-
|
|
225
|
+
/** Individual validation rule types */
|
|
226
|
+
export type ValidationRule =
|
|
227
|
+
| 'required'
|
|
228
|
+
| 'string'
|
|
229
|
+
| 'number'
|
|
230
|
+
| 'numeric'
|
|
231
|
+
| 'integer'
|
|
232
|
+
| 'email'
|
|
233
|
+
| 'url'
|
|
234
|
+
| 'boolean'
|
|
235
|
+
| 'date'
|
|
236
|
+
| 'array'
|
|
237
|
+
| 'object'
|
|
238
|
+
| 'nullable'
|
|
239
|
+
| `min:${number}`
|
|
240
|
+
| `max:${number}`
|
|
241
|
+
| `between:${number},${number}`
|
|
242
|
+
| `in:${string}`
|
|
243
|
+
| `not_in:${string}`
|
|
244
|
+
| `regex:${string}`
|
|
245
|
+
| `size:${number}`
|
|
246
|
+
| `digits:${number}`
|
|
247
|
+
| `digits_between:${number},${number}`;
|
|
248
|
+
|
|
249
|
+
/** Validation rule as pipe-separated string */
|
|
250
|
+
export type ValidationRuleString = string;
|
|
182
251
|
|
|
183
252
|
export interface ValidationResult {
|
|
184
253
|
valid: boolean;
|
|
@@ -187,7 +256,11 @@ declare module 'outlet-orm' {
|
|
|
187
256
|
|
|
188
257
|
export type EventCallback<T extends Model = Model> = (model: T) => boolean | void | Promise<boolean | void>;
|
|
189
258
|
|
|
190
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Base Model class with optional generic for typed attributes
|
|
261
|
+
* @template TAttributes - Type of model attributes (defaults to Record<string, any>)
|
|
262
|
+
*/
|
|
263
|
+
export class Model<TAttributes extends Record<string, any> = Record<string, any>> {
|
|
191
264
|
static table: string;
|
|
192
265
|
static primaryKey: string;
|
|
193
266
|
static timestamps: boolean;
|
|
@@ -204,21 +277,25 @@ declare module 'outlet-orm' {
|
|
|
204
277
|
static globalScopes: Record<string, (qb: QueryBuilder<any>) => void>;
|
|
205
278
|
|
|
206
279
|
// Events
|
|
207
|
-
static eventListeners: Record<
|
|
280
|
+
static eventListeners: Record<ModelEventName, EventCallback[]>;
|
|
208
281
|
|
|
209
282
|
// Validation
|
|
210
|
-
static rules: Record<string,
|
|
283
|
+
static rules: Record<string, ValidationRuleString | ValidationRule[]>;
|
|
211
284
|
|
|
212
|
-
attributes
|
|
213
|
-
|
|
285
|
+
/** Model attributes with optional typing */
|
|
286
|
+
attributes: TAttributes;
|
|
287
|
+
/** Original attributes before modifications */
|
|
288
|
+
original: TAttributes;
|
|
289
|
+
/** Loaded relations */
|
|
214
290
|
relations: Record<string, any>;
|
|
291
|
+
/** Whether the model exists in database */
|
|
215
292
|
exists: boolean;
|
|
216
293
|
|
|
217
|
-
constructor(attributes?:
|
|
294
|
+
constructor(attributes?: Partial<TAttributes>);
|
|
218
295
|
|
|
219
|
-
// Event registration
|
|
220
|
-
static on(event:
|
|
221
|
-
static fireEvent(event:
|
|
296
|
+
// Event registration with typed event names
|
|
297
|
+
static on(event: ModelEventName, callback: EventCallback): void;
|
|
298
|
+
static fireEvent(event: ModelEventName, model: Model): Promise<boolean>;
|
|
222
299
|
static creating(callback: EventCallback): void;
|
|
223
300
|
static created(callback: EventCallback): void;
|
|
224
301
|
static updating(callback: EventCallback): void;
|
|
@@ -273,16 +350,21 @@ declare module 'outlet-orm' {
|
|
|
273
350
|
/** Control visibility of hidden attributes (false = hide, true = show) */
|
|
274
351
|
static withoutHidden<T extends Model>(this: new () => T, show?: boolean): QueryBuilder<T>;
|
|
275
352
|
|
|
276
|
-
// Instance methods
|
|
277
|
-
|
|
353
|
+
// Instance methods with typed attributes
|
|
354
|
+
/** Fill model with attributes */
|
|
355
|
+
fill(attributes: Partial<TAttributes>): this;
|
|
356
|
+
/** Set a single attribute with type safety */
|
|
357
|
+
setAttribute<K extends keyof TAttributes>(key: K, value: TAttributes[K]): this;
|
|
278
358
|
setAttribute(key: string, value: any): this;
|
|
359
|
+
/** Get a single attribute with type safety */
|
|
360
|
+
getAttribute<K extends keyof TAttributes>(key: K): TAttributes[K];
|
|
279
361
|
getAttribute(key: string): any;
|
|
280
362
|
castAttribute(key: string, value: any): any;
|
|
281
363
|
save(): Promise<this>;
|
|
282
364
|
destroy(): Promise<boolean>;
|
|
283
|
-
getDirty():
|
|
365
|
+
getDirty(): Partial<TAttributes>;
|
|
284
366
|
isDirty(): boolean;
|
|
285
|
-
toJSON():
|
|
367
|
+
toJSON(): TAttributes;
|
|
286
368
|
/** Load relations on an existing instance. Supports dot-notation and arrays. */
|
|
287
369
|
load(...relations: string[] | [string[]]): Promise<this>;
|
|
288
370
|
|
|
@@ -315,6 +397,21 @@ declare module 'outlet-orm' {
|
|
|
315
397
|
localKey?: string,
|
|
316
398
|
throughLocalKey?: string
|
|
317
399
|
): HasManyThroughRelation<T>;
|
|
400
|
+
/** Has one through intermediate model */
|
|
401
|
+
hasOneThrough<T extends Model>(
|
|
402
|
+
relatedFinal: new () => T,
|
|
403
|
+
through: new () => Model,
|
|
404
|
+
foreignKeyOnThrough?: string,
|
|
405
|
+
throughKeyOnFinal?: string,
|
|
406
|
+
localKey?: string,
|
|
407
|
+
throughLocalKey?: string
|
|
408
|
+
): HasOneThroughRelation<T>;
|
|
409
|
+
/** Polymorphic one-to-one relation */
|
|
410
|
+
morphOne<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphOneRelation<T>;
|
|
411
|
+
/** Polymorphic one-to-many relation */
|
|
412
|
+
morphMany<T extends Model>(related: new () => T, name: string, typeColumn?: string, idColumn?: string, localKey?: string): MorphManyRelation<T>;
|
|
413
|
+
/** Inverse polymorphic relation */
|
|
414
|
+
morphTo<T extends Model>(): MorphToRelation<T>;
|
|
318
415
|
}
|
|
319
416
|
|
|
320
417
|
// ==================== Relations ====================
|
|
@@ -379,4 +476,185 @@ declare module 'outlet-orm' {
|
|
|
379
476
|
get(): Promise<T | null>;
|
|
380
477
|
eagerLoad(models: Model[], relationName: string, constraint?: (qb: QueryBuilder<T>) => void): Promise<void>;
|
|
381
478
|
}
|
|
479
|
+
|
|
480
|
+
// ==================== Schema Builder (Migrations) ====================
|
|
481
|
+
|
|
482
|
+
/** Foreign key action types */
|
|
483
|
+
export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION' | 'SET DEFAULT';
|
|
484
|
+
|
|
485
|
+
/** Schema builder for database migrations */
|
|
486
|
+
export interface SchemaBuilder {
|
|
487
|
+
/** Create a new table */
|
|
488
|
+
createTable(name: string, callback: (table: TableBuilder) => void): Promise<void>;
|
|
489
|
+
/** Drop a table */
|
|
490
|
+
dropTable(name: string): Promise<void>;
|
|
491
|
+
/** Drop a table if it exists */
|
|
492
|
+
dropTableIfExists(name: string): Promise<void>;
|
|
493
|
+
/** Rename a table */
|
|
494
|
+
renameTable(from: string, to: string): Promise<void>;
|
|
495
|
+
/** Check if table exists */
|
|
496
|
+
hasTable(name: string): Promise<boolean>;
|
|
497
|
+
/** Modify an existing table */
|
|
498
|
+
table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
|
|
499
|
+
/** Check if column exists */
|
|
500
|
+
hasColumn(table: string, column: string): Promise<boolean>;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** Table builder for creating/modifying tables */
|
|
504
|
+
export interface TableBuilder {
|
|
505
|
+
// Primary keys
|
|
506
|
+
/** Auto-incrementing primary key */
|
|
507
|
+
id(name?: string): ColumnBuilder;
|
|
508
|
+
/** Big integer auto-incrementing primary key */
|
|
509
|
+
bigIncrements(name?: string): ColumnBuilder;
|
|
510
|
+
/** UUID primary key */
|
|
511
|
+
uuid(name?: string): ColumnBuilder;
|
|
512
|
+
|
|
513
|
+
// Numeric types
|
|
514
|
+
/** Integer column */
|
|
515
|
+
integer(name: string): ColumnBuilder;
|
|
516
|
+
/** Big integer column */
|
|
517
|
+
bigInteger(name: string): ColumnBuilder;
|
|
518
|
+
/** Small integer column */
|
|
519
|
+
smallInteger(name: string): ColumnBuilder;
|
|
520
|
+
/** Tiny integer column */
|
|
521
|
+
tinyInteger(name: string): ColumnBuilder;
|
|
522
|
+
/** Decimal column */
|
|
523
|
+
decimal(name: string, precision?: number, scale?: number): ColumnBuilder;
|
|
524
|
+
/** Float column */
|
|
525
|
+
float(name: string, precision?: number, scale?: number): ColumnBuilder;
|
|
526
|
+
/** Double column */
|
|
527
|
+
double(name: string, precision?: number, scale?: number): ColumnBuilder;
|
|
528
|
+
|
|
529
|
+
// String types
|
|
530
|
+
/** String/VARCHAR column */
|
|
531
|
+
string(name: string, length?: number): ColumnBuilder;
|
|
532
|
+
/** Text column */
|
|
533
|
+
text(name: string): ColumnBuilder;
|
|
534
|
+
/** Medium text column */
|
|
535
|
+
mediumText(name: string): ColumnBuilder;
|
|
536
|
+
/** Long text column */
|
|
537
|
+
longText(name: string): ColumnBuilder;
|
|
538
|
+
/** Char column */
|
|
539
|
+
char(name: string, length?: number): ColumnBuilder;
|
|
540
|
+
|
|
541
|
+
// Boolean
|
|
542
|
+
/** Boolean column */
|
|
543
|
+
boolean(name: string): ColumnBuilder;
|
|
544
|
+
|
|
545
|
+
// Date/Time
|
|
546
|
+
/** Date column */
|
|
547
|
+
date(name: string): ColumnBuilder;
|
|
548
|
+
/** DateTime column */
|
|
549
|
+
dateTime(name: string): ColumnBuilder;
|
|
550
|
+
/** Timestamp column */
|
|
551
|
+
timestamp(name: string): ColumnBuilder;
|
|
552
|
+
/** Time column */
|
|
553
|
+
time(name: string): ColumnBuilder;
|
|
554
|
+
/** Year column */
|
|
555
|
+
year(name: string): ColumnBuilder;
|
|
556
|
+
/** Add created_at and updated_at columns */
|
|
557
|
+
timestamps(): void;
|
|
558
|
+
/** Add nullable deleted_at column for soft deletes */
|
|
559
|
+
softDeletes(): void;
|
|
560
|
+
|
|
561
|
+
// Binary
|
|
562
|
+
/** Binary/Blob column */
|
|
563
|
+
binary(name: string): ColumnBuilder;
|
|
564
|
+
/** Blob column */
|
|
565
|
+
blob(name: string): ColumnBuilder;
|
|
566
|
+
|
|
567
|
+
// JSON
|
|
568
|
+
/** JSON column */
|
|
569
|
+
json(name: string): ColumnBuilder;
|
|
570
|
+
/** JSONB column (PostgreSQL) */
|
|
571
|
+
jsonb(name: string): ColumnBuilder;
|
|
572
|
+
|
|
573
|
+
// Enum
|
|
574
|
+
/** Enum column */
|
|
575
|
+
enum(name: string, values: string[]): ColumnBuilder;
|
|
576
|
+
|
|
577
|
+
// Indexes
|
|
578
|
+
/** Add primary key constraint */
|
|
579
|
+
primary(columns: string | string[]): void;
|
|
580
|
+
/** Add unique constraint */
|
|
581
|
+
unique(columns: string | string[]): void;
|
|
582
|
+
/** Add index */
|
|
583
|
+
index(columns: string | string[], name?: string): void;
|
|
584
|
+
/** Add foreign key */
|
|
585
|
+
foreign(column: string): ForeignKeyBuilder;
|
|
586
|
+
|
|
587
|
+
// Modifications
|
|
588
|
+
/** Drop a column */
|
|
589
|
+
dropColumn(name: string | string[]): void;
|
|
590
|
+
/** Rename a column */
|
|
591
|
+
renameColumn(from: string, to: string): void;
|
|
592
|
+
/** Drop an index */
|
|
593
|
+
dropIndex(name: string): void;
|
|
594
|
+
/** Drop a unique constraint */
|
|
595
|
+
dropUnique(name: string): void;
|
|
596
|
+
/** Drop a foreign key */
|
|
597
|
+
dropForeign(name: string): void;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** Column builder for column definitions */
|
|
601
|
+
export interface ColumnBuilder {
|
|
602
|
+
/** Make column nullable */
|
|
603
|
+
nullable(): this;
|
|
604
|
+
/** Set default value */
|
|
605
|
+
default(value: any): this;
|
|
606
|
+
/** Make column unsigned (numeric only) */
|
|
607
|
+
unsigned(): this;
|
|
608
|
+
/** Add unique constraint */
|
|
609
|
+
unique(): this;
|
|
610
|
+
/** Make column primary key */
|
|
611
|
+
primary(): this;
|
|
612
|
+
/** Add index */
|
|
613
|
+
index(): this;
|
|
614
|
+
/** Add auto increment */
|
|
615
|
+
autoIncrement(): this;
|
|
616
|
+
/** Add comment */
|
|
617
|
+
comment(text: string): this;
|
|
618
|
+
/** Add after clause (MySQL) */
|
|
619
|
+
after(column: string): this;
|
|
620
|
+
/** Add first clause (MySQL) */
|
|
621
|
+
first(): this;
|
|
622
|
+
/** Set character set */
|
|
623
|
+
charset(charset: string): this;
|
|
624
|
+
/** Set collation */
|
|
625
|
+
collation(collation: string): this;
|
|
626
|
+
/** Add references for foreign key */
|
|
627
|
+
references(column: string): ForeignKeyBuilder;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/** Foreign key builder */
|
|
631
|
+
export interface ForeignKeyBuilder {
|
|
632
|
+
/** Referenced table */
|
|
633
|
+
on(table: string): this;
|
|
634
|
+
/** Referenced column */
|
|
635
|
+
references(column: string): this;
|
|
636
|
+
/** On delete action */
|
|
637
|
+
onDelete(action: ForeignKeyAction): this;
|
|
638
|
+
/** On update action */
|
|
639
|
+
onUpdate(action: ForeignKeyAction): this;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** Migration interface for typed migrations */
|
|
643
|
+
export interface MigrationInterface {
|
|
644
|
+
/** Run the migration */
|
|
645
|
+
up(schema: SchemaBuilder): Promise<void>;
|
|
646
|
+
/** Reverse the migration */
|
|
647
|
+
down(schema: SchemaBuilder): Promise<void>;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/** Schema class export */
|
|
651
|
+
export class Schema {
|
|
652
|
+
static create(name: string, callback: (table: TableBuilder) => void): Promise<void>;
|
|
653
|
+
static drop(name: string): Promise<void>;
|
|
654
|
+
static dropIfExists(name: string): Promise<void>;
|
|
655
|
+
static table(name: string, callback: (table: TableBuilder) => void): Promise<void>;
|
|
656
|
+
static rename(from: string, to: string): Promise<void>;
|
|
657
|
+
static hasTable(name: string): Promise<boolean>;
|
|
658
|
+
static hasColumn(table: string, column: string): Promise<boolean>;
|
|
659
|
+
}
|
|
382
660
|
}
|