outlet-orm 6.5.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/init.js +122 -0
- package/bin/mcp.js +78 -0
- package/bin/migrate.js +25 -0
- package/docs/skills/outlet-orm/ADVANCED.md +575 -0
- package/docs/skills/outlet-orm/AI.md +220 -0
- package/docs/skills/outlet-orm/API.md +522 -0
- package/docs/skills/outlet-orm/BACKUP.md +150 -0
- package/docs/skills/outlet-orm/MIGRATIONS.md +605 -0
- package/docs/skills/outlet-orm/MODELS.md +427 -0
- package/docs/skills/outlet-orm/QUERIES.md +345 -0
- package/docs/skills/outlet-orm/RELATIONS.md +555 -0
- package/docs/skills/outlet-orm/SECURITY.md +386 -0
- package/docs/skills/outlet-orm/SEEDS.md +98 -0
- package/docs/skills/outlet-orm/SKILL.md +205 -0
- package/docs/skills/outlet-orm/TYPESCRIPT.md +480 -0
- package/package.json +7 -3
- package/src/AI/AISafetyGuardrails.js +146 -0
- package/src/AI/MCPServer.js +685 -0
- package/src/AI/PromptGenerator.js +318 -0
- package/src/index.js +11 -1
- package/types/index.d.ts +106 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
# Outlet ORM - API Reference
|
|
2
|
+
|
|
3
|
+
[← Back to Index](SKILL.md) | [Previous: Advanced](ADVANCED.md)
|
|
4
|
+
|
|
5
|
+
> 📘 **TypeScript** : Full type definitions available. Import types from`outlet-orm`. See [TYPESCRIPT.md](TYPESCRIPT.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## DatabaseConnection
|
|
10
|
+
|
|
11
|
+
### Constructor
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
const { DatabaseConnection } = require('outlet-orm');
|
|
15
|
+
|
|
16
|
+
// From .env (automatic)
|
|
17
|
+
const db = new DatabaseConnection();
|
|
18
|
+
|
|
19
|
+
// Manual configuration
|
|
20
|
+
const db = new DatabaseConnection({
|
|
21
|
+
driver: 'mysql', // mysql | postgres | sqlite
|
|
22
|
+
host: 'localhost',
|
|
23
|
+
port: 3306,
|
|
24
|
+
database: 'myapp',
|
|
25
|
+
user: 'root',
|
|
26
|
+
password: 'secret'
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Methods
|
|
31
|
+
|
|
32
|
+
| Method | Description |
|
|
33
|
+
|--------|-------------|
|
|
34
|
+
|`connect()`| Establish connection (called automatically) |
|
|
35
|
+
|`close()`| Close connection |
|
|
36
|
+
|`disconnect()`| Alias for close() |
|
|
37
|
+
|
|
38
|
+
### Transaction Methods
|
|
39
|
+
|
|
40
|
+
| Method | Description |
|
|
41
|
+
|--------|-------------|
|
|
42
|
+
|`beginTransaction()`| Start transaction |
|
|
43
|
+
|`commit()`| Commit transaction |
|
|
44
|
+
|`rollback()`| Rollback transaction |
|
|
45
|
+
|`transaction(callback)`| Execute in transaction (auto commit/rollback) |
|
|
46
|
+
|
|
47
|
+
### Query Methods
|
|
48
|
+
|
|
49
|
+
| Method | Description |
|
|
50
|
+
|--------|-------------|
|
|
51
|
+
|`select(table, query)`| Execute SELECT |
|
|
52
|
+
|`insert(table, data)`| Insert record |
|
|
53
|
+
|`insertMany(table, data[])`| Insert multiple records |
|
|
54
|
+
|`update(table, data, query)`| Update records |
|
|
55
|
+
|`delete(table, query)`| Delete records |
|
|
56
|
+
|`count(table, query)`| Count records |
|
|
57
|
+
|`executeRawQuery(sql, params?)`| Raw query (normalised results) |
|
|
58
|
+
|`execute(sql, params?)`| Raw query (native driver results) |
|
|
59
|
+
|`increment(table, column, query, amount?)`| Atomic increment |
|
|
60
|
+
|`decrement(table, column, query, amount?)`| Atomic decrement |
|
|
61
|
+
|
|
62
|
+
### Query Logging
|
|
63
|
+
|
|
64
|
+
| Method | Description |
|
|
65
|
+
|--------|-------------|
|
|
66
|
+
|`enableQueryLog()`| Enable query logging |
|
|
67
|
+
|`disableQueryLog()`| Disable query logging |
|
|
68
|
+
|`getQueryLog()`| Get array of logged queries |
|
|
69
|
+
|`flushQueryLog()`| Clear query log |
|
|
70
|
+
|`isLogging()`| Check if logging is enabled |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Model (Static Methods)
|
|
75
|
+
|
|
76
|
+
### Connection
|
|
77
|
+
|
|
78
|
+
| Method | Description |
|
|
79
|
+
|--------|-------------|
|
|
80
|
+
|`setConnection(db)`| Set default connection |
|
|
81
|
+
|`getConnection()`| Get current connection |
|
|
82
|
+
|`setMorphMap(map)`| Set polymorphic mapping |
|
|
83
|
+
|
|
84
|
+
### Query
|
|
85
|
+
|
|
86
|
+
| Method | Description |
|
|
87
|
+
|--------|-------------|
|
|
88
|
+
|`query()`| Get QueryBuilder instance |
|
|
89
|
+
|`all()`| Get all records |
|
|
90
|
+
|`find(id)`| Find by ID |
|
|
91
|
+
|`findOrFail(id)`| Find or throw error |
|
|
92
|
+
|`first()`| Get first record |
|
|
93
|
+
|`where(col, op?, val)`| WHERE clause |
|
|
94
|
+
|`whereIn(col, vals)`| WHERE IN |
|
|
95
|
+
|`whereNotIn(col, vals)`| WHERE NOT IN |
|
|
96
|
+
|`whereNull(col)`| WHERE IS NULL |
|
|
97
|
+
|`whereNotNull(col)`| WHERE IS NOT NULL |
|
|
98
|
+
|`whereBetween(col, [min, max])`| WHERE BETWEEN |
|
|
99
|
+
|`whereLike(col, pattern)`| WHERE LIKE |
|
|
100
|
+
|`orWhere(col, op?, val)`| OR WHERE |
|
|
101
|
+
|
|
102
|
+
### CRUD
|
|
103
|
+
|
|
104
|
+
| Method | Description |
|
|
105
|
+
|--------|-------------|
|
|
106
|
+
|`create(attrs)`| Create and save |
|
|
107
|
+
|`insert(data)`| Raw insert |
|
|
108
|
+
|`update(attrs)`| Bulk update |
|
|
109
|
+
|`updateById(id, attrs)`| Update by ID |
|
|
110
|
+
|`updateAndFetchById(id, attrs, rels?)`| Update + fetch with relationships |
|
|
111
|
+
|`delete()`| Bulk delete |
|
|
112
|
+
|
|
113
|
+
### Relationships
|
|
114
|
+
|
|
115
|
+
| Method | Description |
|
|
116
|
+
|--------|-------------|
|
|
117
|
+
|`with(...relationships)`| Eager load relationships |
|
|
118
|
+
|`withCount(relation)`| Add relation count |
|
|
119
|
+
|`whereHas(rel, callback?)`| Filter by relation existence |
|
|
120
|
+
|`has(rel, op?, count)`| Filter by relation count |
|
|
121
|
+
|`whereDoesntHave(rel, callback?)`| Filter by relation absence |
|
|
122
|
+
|
|
123
|
+
### Query Modifiers
|
|
124
|
+
|
|
125
|
+
| Method | Description |
|
|
126
|
+
|--------|-------------|
|
|
127
|
+
|`select(...cols)`| Select columns |
|
|
128
|
+
|`columns([...])`| Select columns (alias) |
|
|
129
|
+
|`distinct()`| SELECT DISTINCT |
|
|
130
|
+
|`orderBy(col, dir?)`| ORDER BY |
|
|
131
|
+
|`ordrer(col, dir?)`| ORDER BY (typo alias) |
|
|
132
|
+
|`limit(n)`| LIMIT |
|
|
133
|
+
|`take(n)`| LIMIT (alias) |
|
|
134
|
+
|`offset(n)`| OFFSET |
|
|
135
|
+
|`skip(n)`| OFFSET (alias) |
|
|
136
|
+
|`groupBy(...cols)`| GROUP BY |
|
|
137
|
+
|`having(col, op, val)`| HAVING |
|
|
138
|
+
|`join(table, col1, op?, col2)`| INNER JOIN |
|
|
139
|
+
|`leftJoin(table, col1, op?, col2)`| LEFT JOIN |
|
|
140
|
+
|`paginate(page, perPage)`| Pagination |
|
|
141
|
+
|`count()`| Count records |
|
|
142
|
+
|`exists()`| Check existence |
|
|
143
|
+
|
|
144
|
+
### Hidden Attributes
|
|
145
|
+
|
|
146
|
+
| Method | Description |
|
|
147
|
+
|--------|-------------|
|
|
148
|
+
|`withHidden()`| Include hidden attributes |
|
|
149
|
+
|`withoutHidden(show?)`| Control hidden visibility |
|
|
150
|
+
|
|
151
|
+
### Soft Deletes
|
|
152
|
+
|
|
153
|
+
| Method | Description |
|
|
154
|
+
|--------|-------------|
|
|
155
|
+
|`withTrashed()`| Include soft deleted |
|
|
156
|
+
|`onlyTrashed()`| Only soft deleted |
|
|
157
|
+
|
|
158
|
+
### Scopes
|
|
159
|
+
|
|
160
|
+
| Method | Description |
|
|
161
|
+
|--------|-------------|
|
|
162
|
+
|`addGlobalScope(name, callback)`| Add global scope |
|
|
163
|
+
|`removeGlobalScope(name)`| Remove global scope |
|
|
164
|
+
|`withoutGlobalScope(name)`| Query without specific scope |
|
|
165
|
+
|`withoutGlobalScopes()`| Query without all scopes |
|
|
166
|
+
|
|
167
|
+
### Events
|
|
168
|
+
|
|
169
|
+
| Method | Description |
|
|
170
|
+
|--------|-------------|
|
|
171
|
+
|`on(event, callback)`| Register event listener |
|
|
172
|
+
|`creating(callback)`| Before create |
|
|
173
|
+
|`created(callback)`| After create |
|
|
174
|
+
|`updating(callback)`| Before update |
|
|
175
|
+
|`updated(callback)`| After update |
|
|
176
|
+
|`saving(callback)`| Before create/update |
|
|
177
|
+
|`saved(callback)`| After create/update |
|
|
178
|
+
|`deleting(callback)`| Before delete |
|
|
179
|
+
|`deleted(callback)`| After delete |
|
|
180
|
+
|`restoring(callback)`| Before restore |
|
|
181
|
+
|`restored(callback)`| After restore |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Model (Instance Methods)
|
|
186
|
+
|
|
187
|
+
### Attributes
|
|
188
|
+
|
|
189
|
+
| Method | Description |
|
|
190
|
+
|--------|-------------|
|
|
191
|
+
|`fill(attrs)`| Fill attributes |
|
|
192
|
+
|`setAttribute(key, val)`| Set single attribute |
|
|
193
|
+
|`getAttribute(key)`| Get single attribute |
|
|
194
|
+
|`getDirty()`| Get modified attributes |
|
|
195
|
+
|`isDirty()`| Check if modified |
|
|
196
|
+
|`toJSON()`| Convert to plain object |
|
|
197
|
+
|
|
198
|
+
### Persistence
|
|
199
|
+
|
|
200
|
+
| Method | Description |
|
|
201
|
+
|--------|-------------|
|
|
202
|
+
|`save()`| Save (insert or update) |
|
|
203
|
+
|`destroy()`| Delete (soft if enabled) |
|
|
204
|
+
|
|
205
|
+
### Relationships
|
|
206
|
+
|
|
207
|
+
| Method | Description |
|
|
208
|
+
|--------|-------------|
|
|
209
|
+
|`load(...relationships)`| Load relationships on instance |
|
|
210
|
+
|`hasOne(Model, fk, lk)`| Define has-one relation |
|
|
211
|
+
|`hasMany(Model, fk, lk)`| Define has-many relation |
|
|
212
|
+
|`belongsTo(Model, fk, ok)`| Define belongs-to relation |
|
|
213
|
+
|`belongsToMany(Model, pivot, fk, rk)`| Define many-to-many |
|
|
214
|
+
|`hasManyThrough(Model, Through, fk1, fk2)`| Has-many via intermediate |
|
|
215
|
+
|`hasOneThrough(Model, Through, fk1, fk2)`| Has-one via intermediate |
|
|
216
|
+
|`morphOne(Model, name)`| Polymorphic has-one |
|
|
217
|
+
|`morphMany(Model, name)`| Polymorphic has-many |
|
|
218
|
+
|`morphTo(name)`| Polymorphic belongs-to |
|
|
219
|
+
|
|
220
|
+
### Soft Deletes
|
|
221
|
+
|
|
222
|
+
| Method | Description |
|
|
223
|
+
|--------|-------------|
|
|
224
|
+
|`trashed()`| Check if soft deleted |
|
|
225
|
+
|`restore()`| Restore soft deleted |
|
|
226
|
+
|`forceDelete()`| Permanent delete |
|
|
227
|
+
|
|
228
|
+
### Validation
|
|
229
|
+
|
|
230
|
+
| Method | Description |
|
|
231
|
+
|--------|-------------|
|
|
232
|
+
|`validate()`| Validate against rules |
|
|
233
|
+
|`validateOrFail()`| Validate or throw error |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## QueryBuilder
|
|
238
|
+
|
|
239
|
+
### Selection
|
|
240
|
+
|
|
241
|
+
| Method | Description |
|
|
242
|
+
|--------|-------------|
|
|
243
|
+
|`select(...cols)`| Select columns |
|
|
244
|
+
|`columns([...])`| Select columns (alias) |
|
|
245
|
+
|`distinct()`| SELECT DISTINCT |
|
|
246
|
+
|
|
247
|
+
### Conditions
|
|
248
|
+
|
|
249
|
+
| Method | Description |
|
|
250
|
+
|--------|-------------|
|
|
251
|
+
|`where(col, op?, val)`| WHERE clause |
|
|
252
|
+
|`orWhere(col, op?, val)`| OR WHERE |
|
|
253
|
+
|`whereIn(col, vals)`| WHERE IN |
|
|
254
|
+
|`whereNotIn(col, vals)`| WHERE NOT IN |
|
|
255
|
+
|`whereNull(col)`| WHERE IS NULL |
|
|
256
|
+
|`whereNotNull(col)`| WHERE IS NOT NULL |
|
|
257
|
+
|`whereBetween(col, [min, max])`| WHERE BETWEEN |
|
|
258
|
+
|`whereLike(col, pattern)`| WHERE LIKE |
|
|
259
|
+
|
|
260
|
+
### Relational Filters
|
|
261
|
+
|
|
262
|
+
| Method | Description |
|
|
263
|
+
|--------|-------------|
|
|
264
|
+
|`whereHas(rel, callback?)`| Filter by relation |
|
|
265
|
+
|`has(rel, op?, count)`| Relation count filter |
|
|
266
|
+
|`whereDoesntHave(rel, callback?)`| No relation filter |
|
|
267
|
+
|`withCount(rel)`| Add {rel}_count column |
|
|
268
|
+
|
|
269
|
+
### Ordering & Limiting
|
|
270
|
+
|
|
271
|
+
| Method | Description |
|
|
272
|
+
|--------|-------------|
|
|
273
|
+
|`orderBy(col, dir?)`| ORDER BY |
|
|
274
|
+
|`ordrer(col, dir?)`| ORDER BY (typo alias) |
|
|
275
|
+
|`limit(n)`/`take(n)`| LIMIT |
|
|
276
|
+
|`offset(n)`/`skip(n)`| OFFSET |
|
|
277
|
+
|
|
278
|
+
### Grouping
|
|
279
|
+
|
|
280
|
+
| Method | Description |
|
|
281
|
+
|--------|-------------|
|
|
282
|
+
|`groupBy(...cols)`| GROUP BY |
|
|
283
|
+
|`having(col, op, val)`| HAVING |
|
|
284
|
+
|
|
285
|
+
### Joins
|
|
286
|
+
|
|
287
|
+
| Method | Description |
|
|
288
|
+
|--------|-------------|
|
|
289
|
+
|`join(table, col1, op?, col2)`| INNER JOIN |
|
|
290
|
+
|`leftJoin(table, col1, op?, col2)`| LEFT JOIN |
|
|
291
|
+
|
|
292
|
+
### Eager Loading
|
|
293
|
+
|
|
294
|
+
| Method | Description |
|
|
295
|
+
|--------|-------------|
|
|
296
|
+
|`with(...relationships)`| Eager load relationships |
|
|
297
|
+
|`with({ rel: callback })`| Eager load with constraints |
|
|
298
|
+
|
|
299
|
+
### Soft Deletes
|
|
300
|
+
|
|
301
|
+
| Method | Description |
|
|
302
|
+
|--------|-------------|
|
|
303
|
+
|`withTrashed()`| Include soft deleted |
|
|
304
|
+
|`onlyTrashed()`| Only soft deleted |
|
|
305
|
+
|
|
306
|
+
### Scopes
|
|
307
|
+
|
|
308
|
+
| Method | Description |
|
|
309
|
+
|--------|-------------|
|
|
310
|
+
|`withoutGlobalScope(name)`| Without specific scope |
|
|
311
|
+
|`withoutGlobalScopes()`| Without all scopes |
|
|
312
|
+
|
|
313
|
+
### Execution
|
|
314
|
+
|
|
315
|
+
| Method | Description |
|
|
316
|
+
|--------|-------------|
|
|
317
|
+
|`get()`| Execute and get all results |
|
|
318
|
+
|`first()`| Get first result |
|
|
319
|
+
|`firstOrFail()`| First or throw error |
|
|
320
|
+
|`find(id)`| Find by ID |
|
|
321
|
+
|`findOrFail(id)`| Find or throw error |
|
|
322
|
+
|`paginate(page, perPage)`| Paginated results |
|
|
323
|
+
|`count()`| Count results |
|
|
324
|
+
|`exists()`| Check existence |
|
|
325
|
+
|
|
326
|
+
### Mutations
|
|
327
|
+
|
|
328
|
+
| Method | Description |
|
|
329
|
+
|--------|-------------|
|
|
330
|
+
|`insert(data)`| Insert record(s) |
|
|
331
|
+
|`update(attrs)`| Update records |
|
|
332
|
+
|`updateAndFetch(attrs, rels?)`| Update + fetch |
|
|
333
|
+
|`delete()`| Delete records |
|
|
334
|
+
|`increment(col, amount?)`| Atomic increment |
|
|
335
|
+
|`decrement(col, amount?)`| Atomic decrement |
|
|
336
|
+
|
|
337
|
+
### Utility
|
|
338
|
+
|
|
339
|
+
| Method | Description |
|
|
340
|
+
|--------|-------------|
|
|
341
|
+
|`clone()`| Clone QueryBuilder |
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Schema Builder
|
|
346
|
+
|
|
347
|
+
### Table Operations
|
|
348
|
+
|
|
349
|
+
| Method | Description |
|
|
350
|
+
|--------|-------------|
|
|
351
|
+
|`create(table, callback)`| Create table |
|
|
352
|
+
|`table(table, callback)`| Alter table |
|
|
353
|
+
|`drop(table)`| Drop table |
|
|
354
|
+
|`dropIfExists(table)`| Drop if exists |
|
|
355
|
+
|`rename(from, to)`| Rename table |
|
|
356
|
+
|`hasTable(table)`| Check table exists |
|
|
357
|
+
|`hasColumn(table, column)`| Check column exists |
|
|
358
|
+
|
|
359
|
+
### Column Types
|
|
360
|
+
|
|
361
|
+
| Method | SQL Type |
|
|
362
|
+
|--------|----------|
|
|
363
|
+
|`id()`| BIGINT UNSIGNED AUTO_INCREMENT PK |
|
|
364
|
+
|`string(col, length?)`| VARCHAR |
|
|
365
|
+
|`text(col)`| TEXT |
|
|
366
|
+
|`integer(col)`| INT |
|
|
367
|
+
|`bigInteger(col)`| BIGINT |
|
|
368
|
+
|`boolean(col)`| TINYINT(1) |
|
|
369
|
+
|`date(col)`| DATE |
|
|
370
|
+
|`datetime(col)`| DATETIME |
|
|
371
|
+
|`timestamp(col)`| TIMESTAMP |
|
|
372
|
+
|`decimal(col, precision, scale)`| DECIMAL |
|
|
373
|
+
|`float(col, precision, scale)`| FLOAT |
|
|
374
|
+
|`json(col)`| JSON |
|
|
375
|
+
|`enum(col, values)`| ENUM |
|
|
376
|
+
|`uuid(col)`| CHAR(36) |
|
|
377
|
+
|`foreignId(col)`| BIGINT UNSIGNED |
|
|
378
|
+
|`timestamps()`| created_at, updated_at |
|
|
379
|
+
|`softDeletes()`| deleted_at |
|
|
380
|
+
|
|
381
|
+
### Column Modifiers
|
|
382
|
+
|
|
383
|
+
| Method | Description |
|
|
384
|
+
|--------|-------------|
|
|
385
|
+
|`nullable()`| Allow NULL |
|
|
386
|
+
|`default(value)`| Default value |
|
|
387
|
+
|`unique()`| UNIQUE constraint |
|
|
388
|
+
|`unsigned()`| UNSIGNED |
|
|
389
|
+
|`comment(text)`| Column comment |
|
|
390
|
+
|`after(column)`| Position after |
|
|
391
|
+
|`first()`| Position first |
|
|
392
|
+
|`useCurrent()`| DEFAULT CURRENT_TIMESTAMP |
|
|
393
|
+
|`useCurrentOnUpdate()`| ON UPDATE CURRENT_TIMESTAMP |
|
|
394
|
+
|
|
395
|
+
### Foreign Keys
|
|
396
|
+
|
|
397
|
+
| Method | Description |
|
|
398
|
+
|--------|-------------|
|
|
399
|
+
|`foreign(col)`| Start FK definition |
|
|
400
|
+
|`references(col)`| Reference column |
|
|
401
|
+
|`on(table)`| Reference table |
|
|
402
|
+
|`onDelete(action)`| ON DELETE action |
|
|
403
|
+
|`onUpdate(action)`| ON UPDATE action |
|
|
404
|
+
|`cascadeOnDelete()`| ON DELETE CASCADE |
|
|
405
|
+
|`cascadeOnUpdate()`| ON UPDATE CASCADE |
|
|
406
|
+
|`constrained(table?)`| Simplified FK |
|
|
407
|
+
|`dropForeign([cols])`| Drop FK |
|
|
408
|
+
|
|
409
|
+
### Indexes
|
|
410
|
+
|
|
411
|
+
| Method | Description |
|
|
412
|
+
|--------|-------------|
|
|
413
|
+
|`index(col)`| Add index |
|
|
414
|
+
|`index([cols])`| Composite index |
|
|
415
|
+
|`unique(col)`| Unique index |
|
|
416
|
+
|`fullText(col)`| Full text index |
|
|
417
|
+
|`dropIndex([cols])`| Drop index |
|
|
418
|
+
|
|
419
|
+
### Column Manipulation
|
|
420
|
+
|
|
421
|
+
| Method | Description |
|
|
422
|
+
|--------|-------------|
|
|
423
|
+
|`renameColumn(from, to)`| Rename column |
|
|
424
|
+
|`dropColumn(col)`| Drop column |
|
|
425
|
+
|`dropColumn([cols])`| Drop multiple columns |
|
|
426
|
+
|`dropTimestamps()`| Drop created_at, updated_at |
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Migration Class
|
|
431
|
+
|
|
432
|
+
### Properties
|
|
433
|
+
|
|
434
|
+
| Property | Description |
|
|
435
|
+
|----------|-------------|
|
|
436
|
+
|`connection`| Database connection |
|
|
437
|
+
|
|
438
|
+
### Methods
|
|
439
|
+
|
|
440
|
+
| Method | Description |
|
|
441
|
+
|--------|-------------|
|
|
442
|
+
|`getSchema()`| Get Schema Builder |
|
|
443
|
+
|`execute(sql)`| Execute raw SQL |
|
|
444
|
+
|
|
445
|
+
### Lifecycle Methods
|
|
446
|
+
|
|
447
|
+
| Method | Description |
|
|
448
|
+
|--------|-------------|
|
|
449
|
+
|`up()`| Run migration |
|
|
450
|
+
|`down()`| Rollback migration |
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Model Static Properties
|
|
455
|
+
|
|
456
|
+
| Property | Type | Default | Description |
|
|
457
|
+
|----------|------|---------|-------------|
|
|
458
|
+
|`table`| string | required | Table name |
|
|
459
|
+
|`primaryKey`| string |`'id'`| Primary key column |
|
|
460
|
+
|`timestamps`| boolean |`true`| Auto timestamps |
|
|
461
|
+
|`softDeletes`| boolean |`false`| Enable soft delete |
|
|
462
|
+
|`DELETED_AT`| string |`'deleted_at'`| Soft delete column |
|
|
463
|
+
|`fillable`| array |`[]`| Mass assignable fields |
|
|
464
|
+
|`hidden`| array |`[]`| Hidden from JSON |
|
|
465
|
+
|`casts`| object |`{}`| Type casting |
|
|
466
|
+
|`rules`| object |`{}`| Validation rules |
|
|
467
|
+
|`connection`| object |`null`| Custom connection |
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Validation Rules
|
|
472
|
+
|
|
473
|
+
| Rule | Description |
|
|
474
|
+
|------|-------------|
|
|
475
|
+
|`required`| Field required |
|
|
476
|
+
|`string`| Must be string |
|
|
477
|
+
|`number`/`numeric`| Must be number |
|
|
478
|
+
|`email`| Valid email |
|
|
479
|
+
|`boolean`| Must be boolean |
|
|
480
|
+
|`date`| Valid date |
|
|
481
|
+
|`min:N`| Min length/value |
|
|
482
|
+
|`max:N`| Max length/value |
|
|
483
|
+
|`in:a,b,c`| Value in list |
|
|
484
|
+
|`regex:pattern`| Match regex |
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Cast Types
|
|
489
|
+
|
|
490
|
+
| Type | Description |
|
|
491
|
+
|------|-------------|
|
|
492
|
+
|`int`/`integer`| Integer |
|
|
493
|
+
|`float`/`double`| Float |
|
|
494
|
+
|`boolean`/`bool`| Boolean |
|
|
495
|
+
|`json`| JSON object |
|
|
496
|
+
|`array`| JSON array |
|
|
497
|
+
|`date`| Date object |
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## Event Names
|
|
502
|
+
|
|
503
|
+
| Event | Description |
|
|
504
|
+
|-------|-------------|
|
|
505
|
+
|`creating`| Before insert |
|
|
506
|
+
|`created`| After insert |
|
|
507
|
+
|`updating`| Before update |
|
|
508
|
+
|`updated`| After update |
|
|
509
|
+
|`saving`| Before insert/update |
|
|
510
|
+
|`saved`| After insert/update |
|
|
511
|
+
|`deleting`| Before delete |
|
|
512
|
+
|`deleted`| After delete |
|
|
513
|
+
|`restoring`| Before restore |
|
|
514
|
+
|`restored`| After restore |
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## References
|
|
519
|
+
|
|
520
|
+
- <https://github.com/omgbwa-yasse/outlet-orm>
|
|
521
|
+
- <https://www.npmjs.com/package/outlet-orm>
|
|
522
|
+
- <https://github.com/omgbwa-yasse/outlet-orm/blob/main/docs/INDEX.md>
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Outlet ORM – Backup Module
|
|
2
|
+
|
|
3
|
+
[← Back to Index](SKILL.md) | [See also: Advanced](ADVANCED.md)
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Use the Backup module when you need to:
|
|
8
|
+
|
|
9
|
+
- take periodic **full / partial / journal** snapshots of the database;
|
|
10
|
+
- **schedule** recurring backups without cron or external dependencies;
|
|
11
|
+
- **encrypt** backup files at rest (AES-256-GCM, built-in Node.js `crypto`);
|
|
12
|
+
- **restore** data from any backup (auto-detects encrypted `.enc` files);
|
|
13
|
+
- manage backup jobs remotely via a **TCP socket daemon**.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick imports
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
const {
|
|
21
|
+
BackupManager,
|
|
22
|
+
BackupScheduler,
|
|
23
|
+
BackupEncryption,
|
|
24
|
+
BackupSocketServer,
|
|
25
|
+
BackupSocketClient,
|
|
26
|
+
} = require('outlet-orm');
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## BackupManager – core API
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
const manager = new BackupManager(connection, {
|
|
35
|
+
backupPath: './database/backups',
|
|
36
|
+
encrypt: true, // AES-256-GCM
|
|
37
|
+
encryptionPassword: 'pwd', // required when encrypt: true
|
|
38
|
+
saltLength: 6, // grain de sable: 4 | 5 | 6
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Full dump (schema + data)
|
|
42
|
+
const file = await manager.full();
|
|
43
|
+
const file = await manager.full({ format: 'json' });
|
|
44
|
+
|
|
45
|
+
// Selected tables only
|
|
46
|
+
const file = await manager.partial(['users', 'orders']);
|
|
47
|
+
|
|
48
|
+
// Transaction log (requires DatabaseConnection.enableQueryLog() first)
|
|
49
|
+
const file = await manager.journal({ flush: true });
|
|
50
|
+
|
|
51
|
+
// Restore – decrypts .enc files automatically
|
|
52
|
+
const { statements } = await manager.restore(filePath);
|
|
53
|
+
const { statements } = await manager.restore(filePath, { encryptionPassword: 'pwd' });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## BackupScheduler – recurring jobs
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const scheduler = new BackupScheduler(connection, { backupPath: './database/backups' });
|
|
62
|
+
|
|
63
|
+
scheduler.schedule('full', {
|
|
64
|
+
intervalMs: 86_400_000, // every 24 h
|
|
65
|
+
name: 'daily_full',
|
|
66
|
+
runNow: true, // fire immediately on registration
|
|
67
|
+
onSuccess: (path) => console.log('done:', path),
|
|
68
|
+
onError: (err) => console.error(err.message),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
scheduler.schedule('partial', {
|
|
72
|
+
intervalMs: 900_000,
|
|
73
|
+
tables: ['orders'],
|
|
74
|
+
name: 'orders_15m',
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
scheduler.activeJobs(); // ['daily_full', 'orders_15m']
|
|
78
|
+
scheduler.stop('orders_15m');
|
|
79
|
+
scheduler.stopAll();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## BackupEncryption – low-level helpers
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
const { encryptedContent, salt } = BackupEncryption.encrypt(sql, 'password', 6);
|
|
88
|
+
const plain = BackupEncryption.decrypt(encryptedContent, 'password');
|
|
89
|
+
BackupEncryption.isEncrypted(content); // boolean
|
|
90
|
+
BackupEncryption.generateSalt(5); // random 5-char alphanumeric
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
File format: `OUTLET_ENC_V1 / <salt(4-6)> / <iv_hex> / <authTag_hex> / <ciphertext_base64>`
|
|
94
|
+
|
|
95
|
+
Key derivation: `scryptSync(password, salt, 32, { N: 16384, r: 8, p: 1 })`
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## BackupSocketServer – TCP daemon
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const server = new BackupSocketServer(connection, {
|
|
103
|
+
port: 9119,
|
|
104
|
+
backupPath: './database/backups',
|
|
105
|
+
encrypt: true,
|
|
106
|
+
encryptionPassword: process.env.BACKUP_PASSWORD,
|
|
107
|
+
});
|
|
108
|
+
await server.listen();
|
|
109
|
+
await server.close(); // graceful shutdown + stopAll()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Push events broadcast to all clients: `jobStart`, `jobDone`, `jobError`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## BackupSocketClient – remote control
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const client = new BackupSocketClient({ port: 9119 });
|
|
120
|
+
await client.connect();
|
|
121
|
+
|
|
122
|
+
await client.ping(); // 'pong'
|
|
123
|
+
await client.status(); // { uptime, jobs, clients }
|
|
124
|
+
await client.jobs(); // string[]
|
|
125
|
+
|
|
126
|
+
await client.schedule('full', { intervalMs: 3_600_000, name: 'hourly', runNow: true });
|
|
127
|
+
await client.run('full'); // → absolute file path
|
|
128
|
+
await client.run('partial', ['users']);
|
|
129
|
+
await client.restore('/path/to/backup.sql');
|
|
130
|
+
await client.restore('/path/to/backup.sql.enc', { encryptionPassword: 'pwd' });
|
|
131
|
+
|
|
132
|
+
await client.stop('hourly');
|
|
133
|
+
await client.stopAll();
|
|
134
|
+
await client.disconnect();
|
|
135
|
+
|
|
136
|
+
// Push events
|
|
137
|
+
client.on('jobDone', ({ name, filePath }) => console.log(filePath));
|
|
138
|
+
client.on('jobError', ({ name, error }) => console.error(error));
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Rules & best practices
|
|
144
|
+
|
|
145
|
+
- Always call `scheduler.stopAll()` (or `server.close()`) before process exit to avoid timer leaks.
|
|
146
|
+
- Enable `DatabaseConnection.enableQueryLog()` **before** operations you want captured in a `journal` backup.
|
|
147
|
+
- For `journal` backups, pass `flush: true` to avoid replaying old entries on the next run.
|
|
148
|
+
- Do not store `encryptionPassword` in source code — use environment variables or a secrets manager.
|
|
149
|
+
- PostgreSQL: schema DDL (`CREATE TABLE`) is **not** included in the dump; only INSERT rows are written.
|
|
150
|
+
- `saltLength` of 6 (default) provides ~56 billion possible salt values — use it unless you have a specific reason to choose 4 or 5.
|