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/core/model.d.ts
CHANGED
|
@@ -1,39 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for all Crudora models. Extend this to define your table schema,
|
|
3
|
+
* configure lifecycle hooks, and control API behaviour via static properties.
|
|
4
|
+
*
|
|
5
|
+
* Use `@Field()` decorators on instance properties to describe columns.
|
|
6
|
+
* Use `@HasMany()`, `@HasOne()`, `@BelongsTo()`, `@BelongsToMany()` for relations.
|
|
7
|
+
*
|
|
8
|
+
* This is a plain class — **not** a decorator. Extend it:
|
|
9
|
+
* ```ts
|
|
10
|
+
* class User extends Model {
|
|
11
|
+
* static tableName = 'users';
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
1
15
|
export declare abstract class Model {
|
|
2
16
|
static tableName?: string;
|
|
3
17
|
static primaryKey?: string;
|
|
4
18
|
static timestamps?: boolean;
|
|
19
|
+
static softDelete?: boolean;
|
|
5
20
|
static fillable?: string[];
|
|
6
21
|
static hidden?: string[];
|
|
22
|
+
static schema?: string;
|
|
7
23
|
static getTableName(): string;
|
|
8
24
|
static getPrimaryKey(): string;
|
|
9
|
-
static beforeCreate?(
|
|
10
|
-
static afterCreate?(
|
|
11
|
-
static
|
|
12
|
-
static
|
|
13
|
-
static
|
|
14
|
-
static
|
|
25
|
+
static beforeCreate?(_data: any): Promise<any>;
|
|
26
|
+
static afterCreate?(_data: any, result: any): Promise<any>;
|
|
27
|
+
static afterCreateMany?(_records: any[]): Promise<any[]>;
|
|
28
|
+
static beforeUpdate?(_id: string, _data: any): Promise<any>;
|
|
29
|
+
static afterUpdate?(_id: string, _data: any, result: any): Promise<any>;
|
|
30
|
+
static beforeDelete?(_id: string): Promise<void>;
|
|
31
|
+
static afterDelete?(_id: string, result: any): Promise<any>;
|
|
15
32
|
static beforeFind?(options?: any): Promise<any>;
|
|
16
|
-
static afterFind?(
|
|
33
|
+
static afterFind?(results: any[]): Promise<any[]>;
|
|
17
34
|
beforeSave?(): Promise<void>;
|
|
18
35
|
afterSave?(): Promise<void>;
|
|
19
|
-
static getSelectObject(prismaClient?: any): any;
|
|
20
36
|
}
|
|
21
37
|
export type ModelConstructor<T extends Model = Model> = {
|
|
22
38
|
new (): T;
|
|
23
39
|
tableName?: string;
|
|
24
40
|
primaryKey?: string;
|
|
25
41
|
timestamps?: boolean;
|
|
42
|
+
softDelete?: boolean;
|
|
26
43
|
fillable?: string[];
|
|
27
44
|
hidden?: string[];
|
|
45
|
+
schema?: string;
|
|
28
46
|
getTableName(): string;
|
|
29
47
|
getPrimaryKey(): string;
|
|
30
48
|
beforeCreate?(data: any): Promise<any>;
|
|
31
49
|
afterCreate?(data: any, result: any): Promise<any>;
|
|
50
|
+
afterCreateMany?(records: any[]): Promise<any[]>;
|
|
32
51
|
beforeUpdate?(id: string, data: any): Promise<any>;
|
|
33
52
|
afterUpdate?(id: string, data: any, result: any): Promise<any>;
|
|
34
53
|
beforeDelete?(id: string): Promise<void>;
|
|
35
54
|
afterDelete?(id: string, result: any): Promise<any>;
|
|
36
55
|
beforeFind?(options?: any): Promise<any>;
|
|
37
|
-
afterFind?(
|
|
56
|
+
afterFind?(results: any[]): Promise<any[]>;
|
|
38
57
|
} & typeof Model;
|
|
39
58
|
//# sourceMappingURL=model.d.ts.map
|
package/dist/core/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,8BAAsB,KAAK;IACzB,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,CAAQ;IAClC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAQ;IACnC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,8BAAsB,KAAK;IACzB,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,CAAQ;IAClC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAQ;IACnC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,CAAS;IACpC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEvB,MAAM,CAAC,YAAY,IAAI,MAAM;IAI7B,MAAM,CAAC,aAAa,IAAI,MAAM;WAKjB,YAAY,CAAC,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIvC,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAInD,eAAe,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;WAIjD,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIpD,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIhE,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAIzC,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIpD,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIxC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAIjD,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,IAAI;IACtD,QAAQ,CAAC,CAAC;IACV,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,IAAI,MAAM,CAAC;IACvB,aAAa,IAAI,MAAM,CAAC;IAExB,YAAY,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACnD,eAAe,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,YAAY,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACnD,WAAW,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,YAAY,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,WAAW,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACpD,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;CAC5C,GAAG,OAAO,KAAK,CAAC"}
|
package/dist/core/model.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Model = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Base class for all Crudora models. Extend this to define your table schema,
|
|
6
|
+
* configure lifecycle hooks, and control API behaviour via static properties.
|
|
7
|
+
*
|
|
8
|
+
* Use `@Field()` decorators on instance properties to describe columns.
|
|
9
|
+
* Use `@HasMany()`, `@HasOne()`, `@BelongsTo()`, `@BelongsToMany()` for relations.
|
|
10
|
+
*
|
|
11
|
+
* This is a plain class — **not** a decorator. Extend it:
|
|
12
|
+
* ```ts
|
|
13
|
+
* class User extends Model {
|
|
14
|
+
* static tableName = 'users';
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
4
18
|
class Model {
|
|
5
19
|
static getTableName() {
|
|
6
20
|
return this.tableName || this.name.toLowerCase() + 's';
|
|
@@ -8,94 +22,43 @@ class Model {
|
|
|
8
22
|
static getPrimaryKey() {
|
|
9
23
|
return this.primaryKey || 'id';
|
|
10
24
|
}
|
|
11
|
-
// Lifecycle Hooks
|
|
12
|
-
static async beforeCreate(
|
|
13
|
-
return
|
|
25
|
+
// Lifecycle Hooks
|
|
26
|
+
static async beforeCreate(_data) {
|
|
27
|
+
return _data;
|
|
14
28
|
}
|
|
15
|
-
static async afterCreate(
|
|
16
|
-
return result;
|
|
29
|
+
static async afterCreate(_data, result) {
|
|
30
|
+
return result;
|
|
17
31
|
}
|
|
18
|
-
static async
|
|
19
|
-
return
|
|
32
|
+
static async afterCreateMany(_records) {
|
|
33
|
+
return _records;
|
|
20
34
|
}
|
|
21
|
-
static async
|
|
22
|
-
return
|
|
35
|
+
static async beforeUpdate(_id, _data) {
|
|
36
|
+
return _data;
|
|
23
37
|
}
|
|
24
|
-
static async
|
|
38
|
+
static async afterUpdate(_id, _data, result) {
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
static async beforeDelete(_id) {
|
|
25
42
|
// Default implementation - do nothing
|
|
26
43
|
}
|
|
27
|
-
static async afterDelete(
|
|
28
|
-
return result;
|
|
44
|
+
static async afterDelete(_id, result) {
|
|
45
|
+
return result;
|
|
29
46
|
}
|
|
30
47
|
static async beforeFind(options) {
|
|
31
|
-
return options;
|
|
48
|
+
return options;
|
|
32
49
|
}
|
|
33
|
-
static async afterFind(
|
|
34
|
-
return
|
|
50
|
+
static async afterFind(results) {
|
|
51
|
+
return results;
|
|
35
52
|
}
|
|
36
|
-
// Instance-level hooks (untuk future enhancement)
|
|
37
53
|
async beforeSave() {
|
|
38
54
|
// Default implementation - do nothing
|
|
39
55
|
}
|
|
40
56
|
async afterSave() {
|
|
41
57
|
// Default implementation - do nothing
|
|
42
58
|
}
|
|
43
|
-
// Method dinamis untuk generate select object
|
|
44
|
-
static getSelectObject(prismaClient) {
|
|
45
|
-
if (!this.hidden || this.hidden.length === 0) {
|
|
46
|
-
return undefined; // Return all fields jika tidak ada hidden
|
|
47
|
-
}
|
|
48
|
-
// Jika ada fillable, gunakan itu sebagai whitelist
|
|
49
|
-
if (this.fillable && this.fillable.length > 0) {
|
|
50
|
-
const selectObject = {};
|
|
51
|
-
// Include primary key jika tidak di-hidden
|
|
52
|
-
const primaryKey = this.getPrimaryKey();
|
|
53
|
-
if (!this.hidden.includes(primaryKey)) {
|
|
54
|
-
selectObject[primaryKey] = true;
|
|
55
|
-
}
|
|
56
|
-
// Include fillable fields jika tidak di-hidden
|
|
57
|
-
this.fillable.forEach(field => {
|
|
58
|
-
if (!this.hidden?.includes(field)) {
|
|
59
|
-
selectObject[field] = true;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
// Include timestamp fields jika timestamps enabled dan tidak di-hidden
|
|
63
|
-
if (this.timestamps) {
|
|
64
|
-
if (!this.hidden.includes('createdAt')) {
|
|
65
|
-
selectObject.createdAt = true;
|
|
66
|
-
}
|
|
67
|
-
if (!this.hidden.includes('updatedAt')) {
|
|
68
|
-
selectObject.updatedAt = true;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return selectObject;
|
|
72
|
-
}
|
|
73
|
-
// Jika tidak ada fillable, gunakan approach exclude dengan Prisma DMMF
|
|
74
|
-
if (prismaClient && prismaClient.dmmf) {
|
|
75
|
-
try {
|
|
76
|
-
const modelName = this.name;
|
|
77
|
-
const modelDef = prismaClient.dmmf.datamodel.models.find((model) => model.name === modelName);
|
|
78
|
-
if (modelDef) {
|
|
79
|
-
const selectObject = {};
|
|
80
|
-
// Include semua field kecuali yang di-hidden
|
|
81
|
-
modelDef.fields.forEach((field) => {
|
|
82
|
-
if (!this.hidden.includes(field.name)) {
|
|
83
|
-
selectObject[field.name] = true;
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
return selectObject;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
console.warn('Failed to use Prisma DMMF for dynamic field selection:', error);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Fallback: return undefined untuk select semua field
|
|
94
|
-
// Lalu filter manual di level aplikasi jika diperlukan
|
|
95
|
-
return undefined;
|
|
96
|
-
}
|
|
97
59
|
}
|
|
98
60
|
exports.Model = Model;
|
|
99
61
|
Model.primaryKey = 'id';
|
|
100
62
|
Model.timestamps = true;
|
|
63
|
+
Model.softDelete = false;
|
|
101
64
|
//# sourceMappingURL=model.js.map
|
package/dist/core/model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":";;;AAAA,MAAsB,KAAK;
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;GAaG;AACH,MAAsB,KAAK;IASzB,MAAM,CAAC,YAAY;QACjB,OAAO,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,aAAa;QAClB,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,kBAAkB;IAClB,MAAM,CAAC,KAAK,CAAC,YAAY,CAAE,KAAU;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAE,KAAU,EAAE,MAAW;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,eAAe,CAAE,QAAe;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAE,GAAW,EAAE,KAAU;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAE,GAAW,EAAE,KAAU,EAAE,MAAW;QAC5D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAE,GAAW;QACpC,sCAAsC;IACxC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAE,GAAW,EAAE,MAAW;QAChD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAE,OAAa;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,SAAS,CAAE,OAAc;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,sCAAsC;IACxC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,sCAAsC;IACxC,CAAC;;AA5DH,sBA6DC;AA3DQ,gBAAU,GAAY,IAAI,CAAC;AAC3B,gBAAU,GAAa,IAAI,CAAC;AAC5B,gBAAU,GAAa,KAAK,CAAC"}
|
|
@@ -1,22 +1,106 @@
|
|
|
1
|
-
import { PrismaClient } from '@prisma/client';
|
|
2
1
|
import { Model, ModelConstructor } from './model';
|
|
2
|
+
export interface FindAllOptions {
|
|
3
|
+
skip?: number;
|
|
4
|
+
take?: number;
|
|
5
|
+
where?: Record<string, any>;
|
|
6
|
+
orderBy?: string | string[];
|
|
7
|
+
order?: 'asc' | 'desc' | Array<'asc' | 'desc'>;
|
|
8
|
+
select?: string[];
|
|
9
|
+
with?: string[];
|
|
10
|
+
withDeleted?: boolean;
|
|
11
|
+
/** When true, fields listed in `static hidden` are included in the result. */
|
|
12
|
+
includeHidden?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface FindByIdOptions {
|
|
15
|
+
select?: string[];
|
|
16
|
+
with?: string[];
|
|
17
|
+
withDeleted?: boolean;
|
|
18
|
+
/** When true, fields listed in `static hidden` are included in the result. */
|
|
19
|
+
includeHidden?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface CursorPaginationOptions {
|
|
22
|
+
take?: number;
|
|
23
|
+
cursor?: string | null;
|
|
24
|
+
cursorField?: string;
|
|
25
|
+
order?: 'asc' | 'desc';
|
|
26
|
+
where?: Record<string, any>;
|
|
27
|
+
select?: string[];
|
|
28
|
+
with?: string[];
|
|
29
|
+
withDeleted?: boolean;
|
|
30
|
+
/** When true, fields listed in `static hidden` are included in the result. */
|
|
31
|
+
includeHidden?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface CursorResult<T> {
|
|
34
|
+
data: T[];
|
|
35
|
+
nextCursor: string | null;
|
|
36
|
+
hasMore: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare class NotFoundError extends Error {
|
|
39
|
+
readonly code = "NOT_FOUND";
|
|
40
|
+
constructor(message: string);
|
|
41
|
+
}
|
|
3
42
|
export declare class Repository<T extends Model> {
|
|
4
|
-
private prisma;
|
|
5
|
-
private modelName;
|
|
6
43
|
private modelClass;
|
|
7
|
-
|
|
8
|
-
private
|
|
9
|
-
|
|
44
|
+
private db;
|
|
45
|
+
private table;
|
|
46
|
+
/** Shared registry — same Map instance as Crudora holds; populated lazily. */
|
|
47
|
+
private registry?;
|
|
48
|
+
constructor(modelClass: ModelConstructor<T>, db: any, table: any,
|
|
49
|
+
/** Shared registry — same Map instance as Crudora holds; populated lazily. */
|
|
50
|
+
registry?: Map<string, Repository<any>> | undefined);
|
|
51
|
+
/**
|
|
52
|
+
* Builds the Drizzle select-column object, merging hidden-field exclusion with
|
|
53
|
+
* an optional explicit field list. Returns `undefined` to select all columns.
|
|
54
|
+
*/
|
|
55
|
+
private buildSelectCols;
|
|
56
|
+
private buildWhere;
|
|
57
|
+
private softDeleteClause;
|
|
58
|
+
private combineWhere;
|
|
59
|
+
/**
|
|
60
|
+
* Batch-loads relations for a list of records. Uses the _in operator so the
|
|
61
|
+
* total number of DB round-trips equals the number of requested relations.
|
|
62
|
+
*/
|
|
63
|
+
private loadRelations;
|
|
10
64
|
create(data: Partial<T>): Promise<T>;
|
|
11
|
-
findById(id: string): Promise<T | null>;
|
|
12
|
-
findAll(options?:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
65
|
+
findById(id: string, opts?: FindByIdOptions): Promise<T | null>;
|
|
66
|
+
findAll(options?: FindAllOptions): Promise<T[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Cursor-based pagination — more efficient than offset for large datasets.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* const page1 = await userRepo.findWithCursor({ take: 10 });
|
|
72
|
+
* const page2 = await userRepo.findWithCursor({ take: 10, cursor: page1.nextCursor });
|
|
73
|
+
*/
|
|
74
|
+
findWithCursor(options: CursorPaginationOptions): Promise<CursorResult<T>>;
|
|
18
75
|
update(id: string, data: Partial<T>): Promise<T>;
|
|
19
76
|
delete(id: string): Promise<T>;
|
|
20
|
-
|
|
77
|
+
hardDelete(id: string): Promise<T>;
|
|
78
|
+
restore(id: string): Promise<T>;
|
|
79
|
+
count(where?: any, withDeleted?: boolean): Promise<number>;
|
|
80
|
+
/** Returns the first record matching `where`, or null. Builds a direct LIMIT 1 query — does not delegate to findAll. */
|
|
81
|
+
findOne(where?: Record<string, any>, opts?: FindByIdOptions): Promise<T | null>;
|
|
82
|
+
/**
|
|
83
|
+
* Returns true if at least one record matches `where`.
|
|
84
|
+
* Uses SELECT pk LIMIT 1 — more efficient than COUNT(*) because the DB stops at the first match.
|
|
85
|
+
*/
|
|
86
|
+
exists(where?: Record<string, any>, withDeleted?: boolean): Promise<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* Inserts multiple records in a single INSERT statement.
|
|
89
|
+
* Calls `beforeCreate` for each row. Calls `afterCreateMany` once with all
|
|
90
|
+
* results — use this hook for batch-aware side effects (e.g. bulk notifications).
|
|
91
|
+
* Individual `afterCreate` is intentionally NOT called per row for performance.
|
|
92
|
+
*/
|
|
93
|
+
createMany(data: Partial<T>[]): Promise<T[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Runs `fn` inside a database transaction. The callback receives a new
|
|
96
|
+
* Repository bound to the transaction connection.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* await userRepo.transaction(async (trx) => {
|
|
100
|
+
* await trx.create({ name: 'Alice' });
|
|
101
|
+
* await trx.update(id, { name: 'Bob' });
|
|
102
|
+
* });
|
|
103
|
+
*/
|
|
104
|
+
transaction<R>(fn: (trx: Repository<T>) => Promise<R>): Promise<R>;
|
|
21
105
|
}
|
|
22
106
|
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":"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"}
|