@cinnabun/db 0.0.6 → 0.0.8
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 +44 -24
- 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/decorators/repository.decorator.d.ts +3 -3
- package/dist/decorators/repository.decorator.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @cinnabun/db
|
|
2
2
|
|
|
3
|
-
Database module for the Cinnabun framework with adapter pattern supporting Drizzle ORM and Prisma.
|
|
3
|
+
Database module for the Cinnabun framework with adapter pattern supporting Drizzle ORM and Prisma. Spring Data-style repositories with constructor injection.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -39,12 +39,13 @@ export const users = sqliteTable("users", {
|
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
// src/main.ts
|
|
42
|
+
import "reflect-metadata";
|
|
42
43
|
import { CinnabunApp, CinnabunFactory } from "@cinnabun/core";
|
|
43
44
|
import { DatabaseModule, DatabasePlugin } from "@cinnabun/db";
|
|
44
45
|
|
|
45
46
|
@CinnabunApp({
|
|
46
47
|
port: 3000,
|
|
47
|
-
scanPaths: [],
|
|
48
|
+
scanPaths: ["./src"],
|
|
48
49
|
imports: [
|
|
49
50
|
DatabaseModule.forRoot({
|
|
50
51
|
adapter: "drizzle",
|
|
@@ -52,26 +53,32 @@ import { DatabaseModule, DatabasePlugin } from "@cinnabun/db";
|
|
|
52
53
|
autoMigrate: true,
|
|
53
54
|
}),
|
|
54
55
|
],
|
|
55
|
-
plugins: [
|
|
56
|
+
plugins: [new DatabasePlugin()],
|
|
56
57
|
})
|
|
57
58
|
class App {}
|
|
58
59
|
|
|
59
60
|
CinnabunFactory.run(App);
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
### 3. Use repositories
|
|
63
|
+
### 3. Use repositories
|
|
63
64
|
|
|
64
65
|
**Option A: Spring Data-style (constructor injection)**
|
|
65
66
|
|
|
67
|
+
Extend `CrudRepositoryBase` and use `@RepositoryEntity`. The framework provides the implementation at runtime.
|
|
68
|
+
|
|
66
69
|
```typescript
|
|
67
|
-
|
|
68
|
-
import { RepositoryEntity,
|
|
69
|
-
import { users } from "
|
|
70
|
+
// src/repositories/user.repository.ts
|
|
71
|
+
import { RepositoryEntity, CrudRepositoryBase } from "@cinnabun/db";
|
|
72
|
+
import { users } from "../schema";
|
|
70
73
|
|
|
71
74
|
type User = typeof users.$inferSelect;
|
|
72
75
|
|
|
73
76
|
@RepositoryEntity(users)
|
|
74
|
-
abstract class UserRepository
|
|
77
|
+
abstract class UserRepository extends CrudRepositoryBase<User, number> {}
|
|
78
|
+
|
|
79
|
+
// src/services/user.service.ts
|
|
80
|
+
import { Service } from "@cinnabun/core";
|
|
81
|
+
import { UserRepository } from "../repositories/user.repository.js";
|
|
75
82
|
|
|
76
83
|
@Service()
|
|
77
84
|
class UserService {
|
|
@@ -81,11 +88,19 @@ class UserService {
|
|
|
81
88
|
return this.userRepo.findAll();
|
|
82
89
|
}
|
|
83
90
|
|
|
91
|
+
async findById(id: number) {
|
|
92
|
+
return this.userRepo.findById(id);
|
|
93
|
+
}
|
|
94
|
+
|
|
84
95
|
async create(data: { name: string; email: string }) {
|
|
85
96
|
return this.userRepo.save(data);
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
99
|
|
|
100
|
+
// src/controllers/user.controller.ts
|
|
101
|
+
import { RestController, GetMapping, PostMapping, Body } from "@cinnabun/core";
|
|
102
|
+
import { UserService } from "../services/user.service.js";
|
|
103
|
+
|
|
89
104
|
@RestController("/api/users")
|
|
90
105
|
class UserController {
|
|
91
106
|
constructor(private readonly userService: UserService) {}
|
|
@@ -102,7 +117,14 @@ class UserController {
|
|
|
102
117
|
}
|
|
103
118
|
```
|
|
104
119
|
|
|
105
|
-
Register `UserRepository` and `UserService` in your module's `providers` array.
|
|
120
|
+
Register `UserRepository` and `UserService` in your module's `providers` array. With `scanPaths: ["./src"]`, scanned modules will discover them automatically.
|
|
121
|
+
|
|
122
|
+
**Prisma:** Use the model name string instead of a table schema:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
@RepositoryEntity("Todo")
|
|
126
|
+
abstract class TodoCrudRepository extends CrudRepositoryBase<Todo, string> {}
|
|
127
|
+
```
|
|
106
128
|
|
|
107
129
|
**Option B: InjectRepository (property injection)**
|
|
108
130
|
|
|
@@ -134,11 +156,17 @@ class UserController {
|
|
|
134
156
|
|
|
135
157
|
## Transactions
|
|
136
158
|
|
|
137
|
-
Use `@Transactional()` to wrap methods in database transactions:
|
|
159
|
+
Use `@Transactional()` to wrap methods in database transactions. Inject `TransactionManager` and pass it to the decorator when using constructor-injected repositories:
|
|
138
160
|
|
|
139
161
|
```typescript
|
|
140
162
|
import { Service } from "@cinnabun/core";
|
|
141
|
-
import {
|
|
163
|
+
import {
|
|
164
|
+
Transactional,
|
|
165
|
+
InjectRepository,
|
|
166
|
+
Repository,
|
|
167
|
+
RepositoryFactory,
|
|
168
|
+
TransactionManager,
|
|
169
|
+
} from "@cinnabun/db";
|
|
142
170
|
import { users, profiles } from "./schema";
|
|
143
171
|
|
|
144
172
|
@Service()
|
|
@@ -192,23 +220,15 @@ interface DatabaseModuleOptions {
|
|
|
192
220
|
|
|
193
221
|
## Repository API
|
|
194
222
|
|
|
195
|
-
**
|
|
223
|
+
**CrudRepositoryBase** (Spring Data-style) — extend this with `@RepositoryEntity`. Do not implement `CrudRepository` directly; TypeScript requires all methods to be implemented.
|
|
196
224
|
|
|
197
225
|
```typescript
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
}
|
|
226
|
+
@RepositoryEntity(users)
|
|
227
|
+
abstract class UserRepository extends CrudRepositoryBase<User, number> {}
|
|
210
228
|
```
|
|
211
229
|
|
|
230
|
+
Methods: `findById`, `findAll`, `findOne`, `findMany`, `save`, `saveAll`, `deleteById`, `delete`, `existsById`, `count`.
|
|
231
|
+
|
|
212
232
|
**Repository** (lower-level, use with `@InjectRepository`):
|
|
213
233
|
|
|
214
234
|
```typescript
|
|
@@ -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,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Marks a class as a Spring Data-style repository bound to the given entity.
|
|
3
|
-
* Use with an abstract class extending
|
|
3
|
+
* Use with an abstract class extending CrudRepositoryBase<T, ID> for constructor injection.
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
6
|
* ```ts
|
|
7
|
-
* @
|
|
8
|
-
* abstract class UserRepository
|
|
7
|
+
* @RepositoryEntity(users)
|
|
8
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
9
9
|
*
|
|
10
10
|
* @Service()
|
|
11
11
|
* class UserService {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { dbMetadataStorage } from "../metadata/db-storage.js";
|
|
2
2
|
/**
|
|
3
3
|
* Marks a class as a Spring Data-style repository bound to the given entity.
|
|
4
|
-
* Use with an abstract class extending
|
|
4
|
+
* Use with an abstract class extending CrudRepositoryBase<T, ID> for constructor injection.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
8
|
-
* @
|
|
9
|
-
* abstract class UserRepository
|
|
8
|
+
* @RepositoryEntity(users)
|
|
9
|
+
* abstract class UserRepository extends CrudRepositoryBase<User, string> {}
|
|
10
10
|
*
|
|
11
11
|
* @Service()
|
|
12
12
|
* class UserService {
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export { DrizzleRepository } from "./adapters/drizzle/drizzle-repository.js";
|
|
|
14
14
|
export { PrismaAdapter } from "./adapters/prisma/prisma.adapter.js";
|
|
15
15
|
export { PrismaRepository } from "./adapters/prisma/prisma-repository.js";
|
|
16
16
|
export { DatabaseException, ConnectionException, MigrationException, TransactionException, RepositoryException, } from "./exceptions/database.exception.js";
|
|
17
|
+
export { CrudRepositoryBase } from "./core/crud-repository-base.js";
|
|
17
18
|
export { registerRepositoryResolvers } from "./core/repository-resolver.js";
|
|
18
19
|
export { DATABASE_ADAPTER_TOKEN, DATABASE_OPTIONS_TOKEN } from "./constants.js";
|
|
19
20
|
export { dbMetadataStorage } from "./metadata/db-storage.js";
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export { PrismaAdapter } from "./adapters/prisma/prisma.adapter.js";
|
|
|
14
14
|
export { PrismaRepository } from "./adapters/prisma/prisma-repository.js";
|
|
15
15
|
// Exceptions
|
|
16
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";
|
|
17
19
|
// Repository resolver (for DI integration)
|
|
18
20
|
export { registerRepositoryResolvers } from "./core/repository-resolver.js";
|
|
19
21
|
// Constants
|
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;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,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"}
|
|
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"}
|