@cinnabun/db 0.0.1 → 0.0.7
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 +64 -0
- package/dist/__tests__/unit/crud-repository-adapter.test.d.ts +1 -0
- package/dist/__tests__/unit/crud-repository-adapter.test.js +30 -0
- package/dist/__tests__/unit/crud-repository-adapter.test.js.map +1 -0
- package/dist/__tests__/unit/repository-decorator.test.d.ts +1 -0
- package/dist/__tests__/unit/repository-decorator.test.js +31 -0
- package/dist/__tests__/unit/repository-decorator.test.js.map +1 -0
- package/dist/core/crud-repository-adapter.d.ts +6 -0
- package/dist/core/crud-repository-adapter.js +52 -0
- package/dist/core/crud-repository-adapter.js.map +1 -0
- package/dist/core/crud-repository-base.d.ts +32 -0
- package/dist/core/crud-repository-base.js +22 -0
- package/dist/core/crud-repository-base.js.map +1 -0
- package/dist/core/database.module.d.ts +2 -3
- package/dist/core/database.module.js.map +1 -1
- package/dist/core/database.plugin.d.ts +3 -1
- package/dist/core/database.plugin.js +10 -1
- package/dist/core/database.plugin.js.map +1 -1
- package/dist/core/repository-resolver.d.ts +11 -0
- package/dist/core/repository-resolver.js +18 -0
- package/dist/core/repository-resolver.js.map +1 -0
- package/dist/decorators/repository.decorator.d.ts +19 -0
- package/dist/decorators/repository.decorator.js +28 -0
- package/dist/decorators/repository.decorator.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/repository.interface.d.ts +16 -0
- package/dist/metadata/db-storage.d.ts +8 -0
- package/dist/metadata/db-storage.js +11 -0
- package/dist/metadata/db-storage.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,51 @@ CinnabunFactory.run(App);
|
|
|
61
61
|
|
|
62
62
|
### 3. Use repositories in controllers
|
|
63
63
|
|
|
64
|
+
**Option A: Spring Data-style (constructor injection)**
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { RestController, GetMapping, PostMapping, Body, Service } from "@cinnabun/core";
|
|
68
|
+
import { RepositoryEntity, CrudRepositoryBase } from "@cinnabun/db";
|
|
69
|
+
import { users } from "./schema";
|
|
70
|
+
|
|
71
|
+
type User = typeof users.$inferSelect;
|
|
72
|
+
|
|
73
|
+
@RepositoryEntity(users)
|
|
74
|
+
abstract class UserRepository extends CrudRepositoryBase<User, number> {}
|
|
75
|
+
|
|
76
|
+
@Service()
|
|
77
|
+
class UserService {
|
|
78
|
+
constructor(private readonly userRepo: UserRepository) {}
|
|
79
|
+
|
|
80
|
+
async findAll() {
|
|
81
|
+
return this.userRepo.findAll();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async create(data: { name: string; email: string }) {
|
|
85
|
+
return this.userRepo.save(data);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@RestController("/api/users")
|
|
90
|
+
class UserController {
|
|
91
|
+
constructor(private readonly userService: UserService) {}
|
|
92
|
+
|
|
93
|
+
@GetMapping("/")
|
|
94
|
+
async findAll() {
|
|
95
|
+
return this.userService.findAll();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@PostMapping("/")
|
|
99
|
+
async create(@Body() body: { name: string; email: string }) {
|
|
100
|
+
return this.userService.create(body);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Register `UserRepository` and `UserService` in your module's `providers` array.
|
|
106
|
+
|
|
107
|
+
**Option B: InjectRepository (property injection)**
|
|
108
|
+
|
|
64
109
|
```typescript
|
|
65
110
|
import { RestController, GetMapping, PostMapping, Body } from "@cinnabun/core";
|
|
66
111
|
import { InjectRepository, Repository, RepositoryFactory } from "@cinnabun/db";
|
|
@@ -147,6 +192,25 @@ interface DatabaseModuleOptions {
|
|
|
147
192
|
|
|
148
193
|
## Repository API
|
|
149
194
|
|
|
195
|
+
**CrudRepository** (Spring Data-style, use with `@RepositoryEntity`):
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface CrudRepository<T, ID> {
|
|
199
|
+
findById(id: ID): Promise<T | null>;
|
|
200
|
+
findAll(options?: QueryOptions): Promise<T[]>;
|
|
201
|
+
findOne(where: Partial<T>): Promise<T | null>;
|
|
202
|
+
findMany(where: Partial<T>, options?: QueryOptions): Promise<T[]>;
|
|
203
|
+
save(entity: Partial<T>): Promise<T>;
|
|
204
|
+
saveAll(entities: Partial<T>[]): Promise<T[]>;
|
|
205
|
+
deleteById(id: ID): Promise<void>;
|
|
206
|
+
delete(entity: T): Promise<void>;
|
|
207
|
+
existsById(id: ID): Promise<boolean>;
|
|
208
|
+
count(where?: Partial<T>): Promise<number>;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Repository** (lower-level, use with `@InjectRepository`):
|
|
213
|
+
|
|
150
214
|
```typescript
|
|
151
215
|
interface Repository<T> {
|
|
152
216
|
findAll(options?: QueryOptions): Promise<T[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { toCrudRepository } from "../../core/crud-repository-adapter.js";
|
|
3
|
+
describe("toCrudRepository", () => {
|
|
4
|
+
it("adapts Repository to CrudRepository", async () => {
|
|
5
|
+
const mockRepo = {
|
|
6
|
+
findAll: async () => [{ id: 1, name: "a" }],
|
|
7
|
+
findById: async (id) => (id === 1 ? { id: 1, name: "a" } : null),
|
|
8
|
+
findOne: async () => ({ id: 1, name: "a" }),
|
|
9
|
+
findMany: async () => [{ id: 1, name: "a" }],
|
|
10
|
+
create: async (data) => ({ id: 1, ...data }),
|
|
11
|
+
update: async (_id, data) => ({ id: 1, ...data }),
|
|
12
|
+
delete: async () => { },
|
|
13
|
+
count: async () => 1,
|
|
14
|
+
exists: async () => true,
|
|
15
|
+
};
|
|
16
|
+
const crud = toCrudRepository(mockRepo);
|
|
17
|
+
expect(await crud.findById(1)).toEqual({ id: 1, name: "a" });
|
|
18
|
+
expect(await crud.findById(999)).toBeNull();
|
|
19
|
+
expect(await crud.findAll()).toHaveLength(1);
|
|
20
|
+
expect(await crud.existsById(1)).toBe(true);
|
|
21
|
+
expect(await crud.existsById(999)).toBe(false);
|
|
22
|
+
expect(await crud.count()).toBe(1);
|
|
23
|
+
const saved = await crud.save({ name: "new" });
|
|
24
|
+
expect(saved).toHaveProperty("id");
|
|
25
|
+
expect(saved.name).toBe("new");
|
|
26
|
+
await crud.deleteById(1);
|
|
27
|
+
await crud.delete({ id: 1, name: "a" });
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=crud-repository-adapter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-repository-adapter.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/crud-repository-adapter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAEzE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,QAAQ,GAAG;YACf,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YAC3C,QAAQ,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YACxE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YAC3C,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YAC5C,MAAM,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;YACjD,MAAM,EAAE,KAAK,EAAE,GAAW,EAAE,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;YAC9D,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;YACtB,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACpB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;SACzB,CAAC;QAEF,MAAM,IAAI,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE/B,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { describe, it, expect, beforeEach } from "bun:test";
|
|
8
|
+
import { RepositoryEntity } from "../../decorators/repository.decorator.js";
|
|
9
|
+
import { dbMetadataStorage } from "../../metadata/db-storage.js";
|
|
10
|
+
const mockEntity = { table: "users" };
|
|
11
|
+
describe("RepositoryEntity decorator", () => {
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
dbMetadataStorage.reset();
|
|
14
|
+
});
|
|
15
|
+
it("registers repository class with entity in metadata", () => {
|
|
16
|
+
let UserRepository = class UserRepository {
|
|
17
|
+
};
|
|
18
|
+
UserRepository = __decorate([
|
|
19
|
+
RepositoryEntity(mockEntity)
|
|
20
|
+
], UserRepository);
|
|
21
|
+
const entity = dbMetadataStorage.getEntityForRepository(UserRepository);
|
|
22
|
+
expect(entity).toBe(mockEntity);
|
|
23
|
+
});
|
|
24
|
+
it("returns undefined for non-repository class", () => {
|
|
25
|
+
class PlainService {
|
|
26
|
+
}
|
|
27
|
+
const entity = dbMetadataStorage.getEntityForRepository(PlainService);
|
|
28
|
+
expect(entity).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=repository-decorator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository-decorator.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/repository-decorator.test.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAEtC,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,UAAU,CAAC,GAAG,EAAE;QACd,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAE5D,IAAe,cAAc,GAA7B,MAAe,cAAc;SAAG,CAAA;QAAjB,cAAc;YAD5B,gBAAgB,CAAC,UAAU,CAAC;WACd,cAAc,CAAG;QAEhC,MAAM,MAAM,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACxE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,YAAY;SAAG;QAErB,MAAM,MAAM,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CrudRepository, Repository } from "../interfaces/repository.interface.js";
|
|
2
|
+
/**
|
|
3
|
+
* Adapts Repository<T> to CrudRepository<T, ID>.
|
|
4
|
+
* Wraps create/update as save(), delete(id) as deleteById, etc.
|
|
5
|
+
*/
|
|
6
|
+
export declare function toCrudRepository<T, ID = string | number>(repo: Repository<T>): CrudRepository<T, ID>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapts Repository<T> to CrudRepository<T, ID>.
|
|
3
|
+
* Wraps create/update as save(), delete(id) as deleteById, etc.
|
|
4
|
+
*/
|
|
5
|
+
export function toCrudRepository(repo) {
|
|
6
|
+
return {
|
|
7
|
+
findById(id) {
|
|
8
|
+
return repo.findById(id);
|
|
9
|
+
},
|
|
10
|
+
findAll(options) {
|
|
11
|
+
return repo.findAll(options);
|
|
12
|
+
},
|
|
13
|
+
findOne(where) {
|
|
14
|
+
return repo.findOne(where);
|
|
15
|
+
},
|
|
16
|
+
findMany(where, options) {
|
|
17
|
+
return repo.findMany(where, options);
|
|
18
|
+
},
|
|
19
|
+
async save(entity) {
|
|
20
|
+
const id = entity.id;
|
|
21
|
+
if (id !== undefined && id !== null) {
|
|
22
|
+
return repo.update(id, entity);
|
|
23
|
+
}
|
|
24
|
+
return repo.create(entity);
|
|
25
|
+
},
|
|
26
|
+
async saveAll(entities) {
|
|
27
|
+
const results = [];
|
|
28
|
+
for (const entity of entities) {
|
|
29
|
+
results.push(await this.save(entity));
|
|
30
|
+
}
|
|
31
|
+
return results;
|
|
32
|
+
},
|
|
33
|
+
deleteById(id) {
|
|
34
|
+
return repo.delete(id);
|
|
35
|
+
},
|
|
36
|
+
async delete(entity) {
|
|
37
|
+
const id = entity.id;
|
|
38
|
+
if (id === undefined || id === null) {
|
|
39
|
+
throw new Error("Entity must have an id to delete");
|
|
40
|
+
}
|
|
41
|
+
return repo.delete(id);
|
|
42
|
+
},
|
|
43
|
+
async existsById(id) {
|
|
44
|
+
const found = await repo.findById(id);
|
|
45
|
+
return found != null;
|
|
46
|
+
},
|
|
47
|
+
count(where) {
|
|
48
|
+
return repo.count(where);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=crud-repository-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-repository-adapter.js","sourceRoot":"","sources":["../../src/core/crud-repository-adapter.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAmB;IAEnB,OAAO;QACL,QAAQ,CAAC,EAAM;YACb,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAqB,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,CAAC,OAAsB;YAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,KAAiB;YACvB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,QAAQ,CAAC,KAAiB,EAAE,OAAsB;YAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAkB;YAC3B,MAAM,EAAE,GAAI,MAAkC,CAAC,EAAE,CAAC;YAClD,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACpC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAqB,EAAE,MAAM,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,QAAsB;YAClC,MAAM,OAAO,GAAQ,EAAE,CAAC;YACxB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,UAAU,CAAC,EAAM;YACf,OAAO,IAAI,CAAC,MAAM,CAAC,EAAqB,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAS;YACpB,MAAM,EAAE,GAAI,MAAkC,CAAC,EAAE,CAAC;YAClD,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAqB,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,EAAM;YACrB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAqB,CAAC,CAAC;YACzD,OAAO,KAAK,IAAI,IAAI,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,KAAkB;YACtB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CrudRepository, QueryOptions } from "../interfaces/repository.interface.js";
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base for Spring Data-style repositories.
|
|
4
|
+
* Extend this with @RepositoryEntity(entity) — the framework provides the implementation at runtime.
|
|
5
|
+
* Do not implement the interface directly; TypeScript requires all methods to be implemented.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* @RepositoryEntity(users)
|
|
10
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
11
|
+
*
|
|
12
|
+
* @Service()
|
|
13
|
+
* class UserService {
|
|
14
|
+
* constructor(private readonly userRepo: UserRepository) {}
|
|
15
|
+
* async getById(id: string) {
|
|
16
|
+
* return this.userRepo.findById(id);
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class CrudRepositoryBase<T, ID = string | number> implements CrudRepository<T, ID> {
|
|
22
|
+
abstract findById(id: ID): Promise<T | null>;
|
|
23
|
+
abstract findAll(options?: QueryOptions): Promise<T[]>;
|
|
24
|
+
abstract findOne(where: Partial<T>): Promise<T | null>;
|
|
25
|
+
abstract findMany(where: Partial<T>, options?: QueryOptions): Promise<T[]>;
|
|
26
|
+
abstract save(entity: Partial<T>): Promise<T>;
|
|
27
|
+
abstract saveAll(entities: Partial<T>[]): Promise<T[]>;
|
|
28
|
+
abstract deleteById(id: ID): Promise<void>;
|
|
29
|
+
abstract delete(entity: T): Promise<void>;
|
|
30
|
+
abstract existsById(id: ID): Promise<boolean>;
|
|
31
|
+
abstract count(where?: Partial<T>): Promise<number>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base for Spring Data-style repositories.
|
|
3
|
+
* Extend this with @RepositoryEntity(entity) — the framework provides the implementation at runtime.
|
|
4
|
+
* Do not implement the interface directly; TypeScript requires all methods to be implemented.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* @RepositoryEntity(users)
|
|
9
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
10
|
+
*
|
|
11
|
+
* @Service()
|
|
12
|
+
* class UserService {
|
|
13
|
+
* constructor(private readonly userRepo: UserRepository) {}
|
|
14
|
+
* async getById(id: string) {
|
|
15
|
+
* return this.userRepo.findById(id);
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class CrudRepositoryBase {
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=crud-repository-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-repository-base.js","sourceRoot":"","sources":["../../src/core/crud-repository-base.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAgB,kBAAkB;CAavC"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import { type Constructor } from "@cinnabun/core";
|
|
1
2
|
import type { DatabaseModuleOptions } from "../interfaces/options.interface.js";
|
|
2
3
|
import type { DatabaseAdapter } from "../interfaces/database-adapter.interface.js";
|
|
3
4
|
import { DatabasePlugin } from "./database.plugin.js";
|
|
4
5
|
export declare class DatabaseModule {
|
|
5
|
-
static forRoot(options: DatabaseModuleOptions):
|
|
6
|
-
new (): {};
|
|
7
|
-
};
|
|
6
|
+
static forRoot(options: DatabaseModuleOptions): Constructor;
|
|
8
7
|
static getAdapter(): DatabaseAdapter;
|
|
9
8
|
static getOptions(): DatabaseModuleOptions;
|
|
10
9
|
static createPlugin(): DatabasePlugin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.module.js","sourceRoot":"","sources":["../../src/core/database.module.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"database.module.js","sourceRoot":"","sources":["../../src/core/database.module.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,MAAM,EAAoB,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,IAAI,gBAAgB,GAA2B,IAAI,CAAC;AACpD,IAAI,cAAc,GAAiC,IAAI,CAAC;AAExD,MAAM,OAAO,cAAc;IAClB,AAAP,MAAM,CAAC,OAAO,CAAC,OAA8B;QAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACtD,gBAAgB,GAAG,OAAO,CAAC;QAC3B,cAAc,GAAG,OAAO,CAAC;QAMzB,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;SAAG,CAAA;QAAxB,qBAAqB;YAJ1B,MAAM,CAAC;gBACN,SAAS,EAAE,EAAE;gBACb,OAAO,EAAE,EAAE;aACZ,CAAC;WACI,qBAAqB,CAAG;QAE9B,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,UAAU;QACf,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;QACJ,CAAC;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,UAAU;QACf,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;QACJ,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,YAAY;QACjB,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAEO,MAAM,CAAC,aAAa,CAAC,OAA8B;QACzD,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,KAAK,SAAS;gBACZ,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,QAAQ;gBACX,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;YACpC;gBACE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { CinnabunPlugin, PluginContext } from "@cinnabun/core";
|
|
1
|
+
import type { CinnabunPlugin, PluginContext, BeforeCreateContext, Container } from "@cinnabun/core";
|
|
2
2
|
export declare class DatabasePlugin implements CinnabunPlugin {
|
|
3
3
|
name: string;
|
|
4
|
+
onBeforeCreate(_context: BeforeCreateContext): Promise<void>;
|
|
5
|
+
getPreRegister(): (container: Container) => void;
|
|
4
6
|
onInit(_context: PluginContext): Promise<void>;
|
|
5
7
|
onShutdown(_context: PluginContext): Promise<void>;
|
|
6
8
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { DatabaseModule } from "./database.module.js";
|
|
2
|
+
import { registerRepositoryResolvers } from "./repository-resolver.js";
|
|
2
3
|
export class DatabasePlugin {
|
|
3
4
|
name = "DatabasePlugin";
|
|
4
|
-
async
|
|
5
|
+
async onBeforeCreate(_context) {
|
|
5
6
|
const adapter = DatabaseModule.getAdapter();
|
|
6
7
|
await adapter.connect();
|
|
7
8
|
}
|
|
9
|
+
getPreRegister() {
|
|
10
|
+
return (container) => {
|
|
11
|
+
registerRepositoryResolvers(container);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
async onInit(_context) {
|
|
15
|
+
// DB already connected in onBeforeCreate
|
|
16
|
+
}
|
|
8
17
|
async onShutdown(_context) {
|
|
9
18
|
const adapter = DatabaseModule.getAdapter();
|
|
10
19
|
if (adapter.isConnected()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.plugin.js","sourceRoot":"","sources":["../../src/core/database.plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"database.plugin.js","sourceRoot":"","sources":["../../src/core/database.plugin.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAEvE,MAAM,OAAO,cAAc;IACzB,IAAI,GAAG,gBAAgB,CAAC;IAExB,KAAK,CAAC,cAAc,CAAC,QAA6B;QAChD,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAED,cAAc;QACZ,OAAO,CAAC,SAAS,EAAE,EAAE;YACnB,2BAA2B,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAuB;QAClC,yCAAyC;IAC3C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAuB;QACtC,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1B,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Constructor } from "@cinnabun/core";
|
|
2
|
+
type ContainerLike = {
|
|
3
|
+
registerResolver<T>(target: Constructor<T>, factory: () => T): void;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Registers @Repository(entity) classes with the DI container so they resolve
|
|
7
|
+
* to CrudRepository implementations. Call this from your plugin's getPreRegister.
|
|
8
|
+
* Automatically invoked when using DatabasePlugin.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerRepositoryResolvers(container: ContainerLike): void;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { dbMetadataStorage } from "../metadata/db-storage.js";
|
|
2
|
+
import { getSharedRepositoryFactory } from "../decorators/inject-repository.decorator.js";
|
|
3
|
+
import { toCrudRepository } from "./crud-repository-adapter.js";
|
|
4
|
+
/**
|
|
5
|
+
* Registers @Repository(entity) classes with the DI container so they resolve
|
|
6
|
+
* to CrudRepository implementations. Call this from your plugin's getPreRegister.
|
|
7
|
+
* Automatically invoked when using DatabasePlugin.
|
|
8
|
+
*/
|
|
9
|
+
export function registerRepositoryResolvers(container) {
|
|
10
|
+
const factory = getSharedRepositoryFactory();
|
|
11
|
+
for (const { target, entity } of dbMetadataStorage.getRepositoryDecorators()) {
|
|
12
|
+
container.registerResolver(target, () => {
|
|
13
|
+
const repo = factory.getRepository(entity);
|
|
14
|
+
return toCrudRepository(repo);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=repository-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository-resolver.js","sourceRoot":"","sources":["../../src/core/repository-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAMhE;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,SAAwB;IAClE,MAAM,OAAO,GAAG,0BAA0B,EAAE,CAAC;IAC7C,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,iBAAiB,CAAC,uBAAuB,EAAE,EAAE,CAAC;QAC7E,SAAS,CAAC,gBAAgB,CAAC,MAAqB,EAAE,GAAG,EAAE;YACrD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC3C,OAAO,gBAAgB,CAAC,IAAI,CAAQ,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marks a class as a Spring Data-style repository bound to the given entity.
|
|
3
|
+
* Use with an abstract class extending CrudRepositoryBase<T, ID> for constructor injection.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* @RepositoryEntity(users)
|
|
8
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
9
|
+
*
|
|
10
|
+
* @Service()
|
|
11
|
+
* class UserService {
|
|
12
|
+
* constructor(private readonly userRepo: UserRepository) {}
|
|
13
|
+
* async getById(id: string) {
|
|
14
|
+
* return this.userRepo.findById(id);
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function RepositoryEntity(entity: unknown): ClassDecorator;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { dbMetadataStorage } from "../metadata/db-storage.js";
|
|
2
|
+
/**
|
|
3
|
+
* Marks a class as a Spring Data-style repository bound to the given entity.
|
|
4
|
+
* Use with an abstract class extending CrudRepositoryBase<T, ID> for constructor injection.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* @RepositoryEntity(users)
|
|
9
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
10
|
+
*
|
|
11
|
+
* @Service()
|
|
12
|
+
* class UserService {
|
|
13
|
+
* constructor(private readonly userRepo: UserRepository) {}
|
|
14
|
+
* async getById(id: string) {
|
|
15
|
+
* return this.userRepo.findById(id);
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function RepositoryEntity(entity) {
|
|
21
|
+
return (target) => {
|
|
22
|
+
dbMetadataStorage.addRepositoryDecorator({
|
|
23
|
+
target,
|
|
24
|
+
entity,
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=repository.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.decorator.js","sourceRoot":"","sources":["../../src/decorators/repository.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAe;IAC9C,OAAO,CAAC,MAAgB,EAAE,EAAE;QAC1B,iBAAiB,CAAC,sBAAsB,CAAC;YACvC,MAAM;YACN,MAAM;SACP,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ export { DatabasePlugin } from "./core/database.plugin.js";
|
|
|
3
3
|
export { RepositoryFactory } from "./core/repository-factory.js";
|
|
4
4
|
export { TransactionManager } from "./core/transaction-manager.js";
|
|
5
5
|
export type { DatabaseAdapter, TransactionContext } from "./interfaces/database-adapter.interface.js";
|
|
6
|
-
export type { Repository, QueryOptions } from "./interfaces/repository.interface.js";
|
|
6
|
+
export type { Repository, CrudRepository, QueryOptions, } from "./interfaces/repository.interface.js";
|
|
7
7
|
export type { DatabaseModuleOptions } from "./interfaces/options.interface.js";
|
|
8
8
|
export { InjectRepository } from "./decorators/inject-repository.decorator.js";
|
|
9
|
+
export { RepositoryEntity } from "./decorators/repository.decorator.js";
|
|
9
10
|
export { Transactional } from "./decorators/transactional.decorator.js";
|
|
10
11
|
export type { TransactionalOptions } from "./decorators/transactional.decorator.js";
|
|
11
12
|
export { DrizzleAdapter } from "./adapters/drizzle/drizzle.adapter.js";
|
|
@@ -13,5 +14,7 @@ export { DrizzleRepository } from "./adapters/drizzle/drizzle-repository.js";
|
|
|
13
14
|
export { PrismaAdapter } from "./adapters/prisma/prisma.adapter.js";
|
|
14
15
|
export { PrismaRepository } from "./adapters/prisma/prisma-repository.js";
|
|
15
16
|
export { DatabaseException, ConnectionException, MigrationException, TransactionException, RepositoryException, } from "./exceptions/database.exception.js";
|
|
17
|
+
export { CrudRepositoryBase } from "./core/crud-repository-base.js";
|
|
18
|
+
export { registerRepositoryResolvers } from "./core/repository-resolver.js";
|
|
16
19
|
export { DATABASE_ADAPTER_TOKEN, DATABASE_OPTIONS_TOKEN } from "./constants.js";
|
|
17
20
|
export { dbMetadataStorage } from "./metadata/db-storage.js";
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { RepositoryFactory } from "./core/repository-factory.js";
|
|
|
5
5
|
export { TransactionManager } from "./core/transaction-manager.js";
|
|
6
6
|
// Decorators
|
|
7
7
|
export { InjectRepository } from "./decorators/inject-repository.decorator.js";
|
|
8
|
+
export { RepositoryEntity } from "./decorators/repository.decorator.js";
|
|
8
9
|
export { Transactional } from "./decorators/transactional.decorator.js";
|
|
9
10
|
// Adapters
|
|
10
11
|
export { DrizzleAdapter } from "./adapters/drizzle/drizzle.adapter.js";
|
|
@@ -13,6 +14,10 @@ export { PrismaAdapter } from "./adapters/prisma/prisma.adapter.js";
|
|
|
13
14
|
export { PrismaRepository } from "./adapters/prisma/prisma-repository.js";
|
|
14
15
|
// Exceptions
|
|
15
16
|
export { DatabaseException, ConnectionException, MigrationException, TransactionException, RepositoryException, } from "./exceptions/database.exception.js";
|
|
17
|
+
// Repository base (extend this with @RepositoryEntity, do not implement CrudRepository directly)
|
|
18
|
+
export { CrudRepositoryBase } from "./core/crud-repository-base.js";
|
|
19
|
+
// Repository resolver (for DI integration)
|
|
20
|
+
export { registerRepositoryResolvers } from "./core/repository-resolver.js";
|
|
16
21
|
// Constants
|
|
17
22
|
export { DATABASE_ADAPTER_TOKEN, DATABASE_OPTIONS_TOKEN } from "./constants.js";
|
|
18
23
|
// Metadata
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAWnE,aAAa;AACb,OAAO,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE1E,aAAa;AACb,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oCAAoC,CAAC;AAE5C,iGAAiG;AACjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,2CAA2C;AAC3C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,YAAY;AACZ,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,WAAW;AACX,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -14,3 +14,19 @@ export interface Repository<T> {
|
|
|
14
14
|
count(where?: Partial<T>): Promise<number>;
|
|
15
15
|
exists(where: Partial<T>): Promise<boolean>;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Spring Data-style CRUD repository interface.
|
|
19
|
+
* Use with @Repository(entity) on an abstract class for constructor injection.
|
|
20
|
+
*/
|
|
21
|
+
export interface CrudRepository<T, ID = string | number> {
|
|
22
|
+
findById(id: ID): Promise<T | null>;
|
|
23
|
+
findAll(options?: QueryOptions): Promise<T[]>;
|
|
24
|
+
findOne(where: Partial<T>): Promise<T | null>;
|
|
25
|
+
findMany(where: Partial<T>, options?: QueryOptions): Promise<T[]>;
|
|
26
|
+
save(entity: Partial<T>): Promise<T>;
|
|
27
|
+
saveAll(entities: Partial<T>[]): Promise<T[]>;
|
|
28
|
+
deleteById(id: ID): Promise<void>;
|
|
29
|
+
delete(entity: T): Promise<void>;
|
|
30
|
+
existsById(id: ID): Promise<boolean>;
|
|
31
|
+
count(where?: Partial<T>): Promise<number>;
|
|
32
|
+
}
|
|
@@ -3,10 +3,18 @@ export interface RepositoryInjectionMetadata {
|
|
|
3
3
|
propertyKey: string;
|
|
4
4
|
entity: unknown;
|
|
5
5
|
}
|
|
6
|
+
export interface RepositoryDecoratorMetadata {
|
|
7
|
+
target: Function;
|
|
8
|
+
entity: unknown;
|
|
9
|
+
}
|
|
6
10
|
declare class DbMetadataStorage {
|
|
7
11
|
private repositoryInjections;
|
|
12
|
+
private repositoryDecorators;
|
|
8
13
|
addRepositoryInjection(injection: RepositoryInjectionMetadata): void;
|
|
9
14
|
getRepositoryInjectionsFor(target: Function): RepositoryInjectionMetadata[];
|
|
15
|
+
addRepositoryDecorator(meta: RepositoryDecoratorMetadata): void;
|
|
16
|
+
getEntityForRepository(target: Function): unknown | undefined;
|
|
17
|
+
getRepositoryDecorators(): RepositoryDecoratorMetadata[];
|
|
10
18
|
reset(): void;
|
|
11
19
|
}
|
|
12
20
|
export declare const dbMetadataStorage: DbMetadataStorage;
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
class DbMetadataStorage {
|
|
2
2
|
repositoryInjections = [];
|
|
3
|
+
repositoryDecorators = [];
|
|
3
4
|
addRepositoryInjection(injection) {
|
|
4
5
|
this.repositoryInjections.push(injection);
|
|
5
6
|
}
|
|
6
7
|
getRepositoryInjectionsFor(target) {
|
|
7
8
|
return this.repositoryInjections.filter((i) => i.target === target);
|
|
8
9
|
}
|
|
10
|
+
addRepositoryDecorator(meta) {
|
|
11
|
+
this.repositoryDecorators.push(meta);
|
|
12
|
+
}
|
|
13
|
+
getEntityForRepository(target) {
|
|
14
|
+
return this.repositoryDecorators.find((r) => r.target === target)?.entity;
|
|
15
|
+
}
|
|
16
|
+
getRepositoryDecorators() {
|
|
17
|
+
return [...this.repositoryDecorators];
|
|
18
|
+
}
|
|
9
19
|
reset() {
|
|
10
20
|
this.repositoryInjections = [];
|
|
21
|
+
this.repositoryDecorators = [];
|
|
11
22
|
}
|
|
12
23
|
}
|
|
13
24
|
export const dbMetadataStorage = new DbMetadataStorage();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-storage.js","sourceRoot":"","sources":["../../src/metadata/db-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"db-storage.js","sourceRoot":"","sources":["../../src/metadata/db-storage.ts"],"names":[],"mappings":"AAWA,MAAM,iBAAiB;IACb,oBAAoB,GAAkC,EAAE,CAAC;IACzD,oBAAoB,GAAkC,EAAE,CAAC;IAEjE,sBAAsB,CAAC,SAAsC;QAC3D,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,0BAA0B,CAAC,MAAgB;QACzC,OAAO,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACtE,CAAC;IAED,sBAAsB,CAAC,IAAiC;QACtD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,sBAAsB,CAAC,MAAgB;QACrC,OAAO,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC;IAC5E,CAAC;IAED,uBAAuB;QACrB,OAAO,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;QAC/B,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC;IACjC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC"}
|