crudora 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +554 -328
  3. package/dist/cli.js +72 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/core/crudora.d.ts +34 -9
  6. package/dist/core/crudora.d.ts.map +1 -1
  7. package/dist/core/crudora.js +254 -105
  8. package/dist/core/crudora.js.map +1 -1
  9. package/dist/core/crudoraServer.d.ts +64 -10
  10. package/dist/core/crudoraServer.d.ts.map +1 -1
  11. package/dist/core/crudoraServer.js +138 -19
  12. package/dist/core/crudoraServer.js.map +1 -1
  13. package/dist/core/drizzleTableBuilder.d.ts +6 -0
  14. package/dist/core/drizzleTableBuilder.d.ts.map +1 -0
  15. package/dist/core/drizzleTableBuilder.js +175 -0
  16. package/dist/core/drizzleTableBuilder.js.map +1 -0
  17. package/dist/core/model.d.ts +28 -9
  18. package/dist/core/model.d.ts.map +1 -1
  19. package/dist/core/model.js +33 -70
  20. package/dist/core/model.js.map +1 -1
  21. package/dist/core/repository.d.ts +98 -14
  22. package/dist/core/repository.d.ts.map +1 -1
  23. package/dist/core/repository.js +561 -103
  24. package/dist/core/repository.js.map +1 -1
  25. package/dist/core/schemaGenerator.d.ts +3 -3
  26. package/dist/core/schemaGenerator.d.ts.map +1 -1
  27. package/dist/core/schemaGenerator.js +237 -32
  28. package/dist/core/schemaGenerator.js.map +1 -1
  29. package/dist/decorators/model.d.ts +56 -1
  30. package/dist/decorators/model.d.ts.map +1 -1
  31. package/dist/decorators/model.js +92 -0
  32. package/dist/decorators/model.js.map +1 -1
  33. package/dist/index.d.ts +7 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +12 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/scripts/copy-assets.js +47 -47
  38. package/dist/scripts/postinstall.js +172 -136
  39. package/dist/templates/.env.example +13 -9
  40. package/dist/templates/drizzle.config.ts +10 -0
  41. package/dist/templates/schema.ts +23 -0
  42. package/dist/types/logger.type.d.ts +7 -0
  43. package/dist/types/logger.type.d.ts.map +1 -0
  44. package/dist/types/logger.type.js +3 -0
  45. package/dist/types/logger.type.js.map +1 -0
  46. package/dist/types/model.type.d.ts +30 -5
  47. package/dist/types/model.type.d.ts.map +1 -1
  48. package/dist/utils/validation.d.ts.map +1 -1
  49. package/dist/utils/validation.js +91 -19
  50. package/dist/utils/validation.js.map +1 -1
  51. package/package.json +108 -94
  52. package/scripts/copy-assets.js +47 -47
  53. package/scripts/postinstall.js +172 -136
  54. package/templates/.env.example +13 -9
  55. package/templates/drizzle.config.ts +10 -0
  56. package/templates/schema.ts +23 -0
  57. package/dist/templates/schema.prisma +0 -22
  58. package/templates/schema.prisma +0 -22
@@ -1,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?(data: any): Promise<any>;
10
- static afterCreate?(data: any, result: any): Promise<any>;
11
- static beforeUpdate?(id: string, data: any): Promise<any>;
12
- static afterUpdate?(id: string, data: any, result: any): Promise<any>;
13
- static beforeDelete?(id: string): Promise<void>;
14
- static afterDelete?(id: string, result: any): Promise<any>;
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?(result: any): Promise<any>;
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?(result: any): Promise<any>;
56
+ afterFind?(results: any[]): Promise<any[]>;
38
57
  } & typeof Model;
39
58
  //# sourceMappingURL=model.d.ts.map
@@ -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;IAEzB,MAAM,CAAC,YAAY,IAAI,MAAM;IAI7B,MAAM,CAAC,aAAa,IAAI,MAAM;WAKjB,YAAY,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAItC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIlD,YAAY,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIlD,WAAW,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAI9D,YAAY,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAIxC,WAAW,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAInD,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;WAIxC,SAAS,CAAC,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAK5C,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG;CAgEhD;AAGD,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,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,IAAI,MAAM,CAAC;IACvB,aAAa,IAAI,MAAM,CAAC;IAGxB,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,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,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACvC,GAAG,OAAO,KAAK,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"}
@@ -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 - Static methods untuk class-level hooks
12
- static async beforeCreate(data) {
13
- return data; // Default implementation - return data unchanged
25
+ // Lifecycle Hooks
26
+ static async beforeCreate(_data) {
27
+ return _data;
14
28
  }
15
- static async afterCreate(data, result) {
16
- return result; // Default implementation - return result unchanged
29
+ static async afterCreate(_data, result) {
30
+ return result;
17
31
  }
18
- static async beforeUpdate(id, data) {
19
- return data; // Default implementation - return data unchanged
32
+ static async afterCreateMany(_records) {
33
+ return _records;
20
34
  }
21
- static async afterUpdate(id, data, result) {
22
- return result; // Default implementation - return result unchanged
35
+ static async beforeUpdate(_id, _data) {
36
+ return _data;
23
37
  }
24
- static async beforeDelete(id) {
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(id, result) {
28
- return result; // Default implementation - return result unchanged
44
+ static async afterDelete(_id, result) {
45
+ return result;
29
46
  }
30
47
  static async beforeFind(options) {
31
- return options; // Default implementation - return options unchanged
48
+ return options;
32
49
  }
33
- static async afterFind(result) {
34
- return result; // Default implementation - return result unchanged
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
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"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"}
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
- constructor(modelClass: ModelConstructor<T>, prisma: PrismaClient);
8
- private getSelectOptions;
9
- private filterHiddenFields;
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
- skip?: number;
14
- take?: number;
15
- where?: any;
16
- orderBy?: any;
17
- }): Promise<T[]>;
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
- count(where?: any): Promise<number>;
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAElD,qBAAa,UAAU,CAAC,CAAC,SAAS,KAAK;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY;IAMjE,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;IAsBpB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA0BpC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA0BvC,OAAO,CAAC,OAAO,CAAC,EAAE;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,GAAG,CAAC;QACZ,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IA2BV,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiChD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAmB9B,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;CAI1C"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqDlD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,eAAe;gBAChB,OAAO,EAAE,MAAM;CAI5B;AAID,qBAAa,UAAU,CAAC,CAAC,SAAS,KAAK;IAEnC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;IACb,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC;gBAJT,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC/B,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG;IAClB,8EAA8E;IACtE,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,YAAA;IAKjD;;;OAGG;IACH,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,YAAY;IASpB;;;OAGG;YACW,aAAa;IA0FrB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA6BpC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAwC/D,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAiDrD;;;;;;OAMG;IACG,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAsG1E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA8DhD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IA2B9B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAQlC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAyB/B,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAWhE,wHAAwH;IAClH,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA6BrF;;;OAGG;IACG,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAelF;;;;;OAKG;IACG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IA2ClD;;;;;;;;;OASG;IACG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAoBzE"}