@avleon/data 0.0.0-stage → 0.4.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Tareq Hossain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,213 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @avleon/data
2
+
3
+ TypeORM and Knex integration for [Avleon](https://avleonjs.github.io).
4
+
5
+ `@avleon/data` is an Avleon [plugin](https://avleonjs.github.io/advanced/plugins).
6
+ Once it is installed, the app gains `app.useTypeORM()` and `app.useKnex()`; nothing
7
+ needs to be imported to enable them.
8
+
9
+ ```bash
10
+ npm install @avleon/data typeorm pg # TypeORM
11
+ npm install @avleon/data knex pg # Knex
12
+ ```
13
+
14
+ Projects created with `avleon new` load the plugin's types through the generated
15
+ `avleon-env.d.ts`. In other projects, add the file yourself and include it in
16
+ `tsconfig.json`:
17
+
18
+ ```typescript
19
+ // avleon-env.d.ts
20
+ /// <reference types="@avleon/data" />
21
+ ```
22
+
23
+ Both methods connect before they resolve, register the connection with the
24
+ container, and close it when the app shuts down (`app.close()`, SIGTERM or SIGINT).
25
+ For a bundled app, which has no `package.json` to discover plugins from, pass the
26
+ plugin explicitly:
27
+
28
+ ```typescript
29
+ import { Avleon } from "@avleon/core";
30
+ import { dataPlugin } from "@avleon/data";
31
+
32
+ const app = Avleon.createApplication({ plugins: [dataPlugin] });
33
+ ```
34
+
35
+ ## Knex
36
+
37
+ `useKnex` connects eagerly and verifies the connection, so it returns a promise:
38
+
39
+ ```typescript
40
+ await app.useKnex({
41
+ client: "mysql",
42
+ connection: {
43
+ host: "127.0.0.1",
44
+ port: 3306,
45
+ user: "root",
46
+ password: "password",
47
+ database: "myapp",
48
+ },
49
+ });
50
+ ```
51
+
52
+ Using a config class:
53
+
54
+ ```typescript
55
+ import { AppConfig, AvleonConfig, Environment } from "@avleon/core";
56
+ import type { Knex } from "knex";
57
+
58
+ @AppConfig
59
+ export class KnexConfig extends AvleonConfig<Knex.Config> {
60
+ config(env: Environment): Knex.Config {
61
+ return {
62
+ client: "mysql",
63
+ connection: {
64
+ host: env.get("DB_HOST") || "127.0.0.1",
65
+ port: Number(env.get("DB_PORT")) || 3306,
66
+ user: env.get("DB_USER") || "root",
67
+ password: env.get("DB_PASS") || "password",
68
+ database: env.get("DB_NAME") || "myapp",
69
+ },
70
+ };
71
+ }
72
+ }
73
+
74
+ await app.useKnex(KnexConfig);
75
+ ```
76
+
77
+ Using in a service:
78
+
79
+ ```typescript
80
+ import { AppService } from "@avleon/core";
81
+ import { KnexDB } from "@avleon/data";
82
+
83
+ @AppService
84
+ export class UsersService {
85
+ constructor(private readonly db: KnexDB) {}
86
+
87
+ async findAll() {
88
+ return this.db.client.select("*").from("users");
89
+ }
90
+
91
+ async page(page: number) {
92
+ return this.db.paginate(this.db.client("users").orderBy("id"), {
93
+ page,
94
+ perPage: 20,
95
+ });
96
+ }
97
+ }
98
+ ```
99
+
100
+ ---
101
+
102
+ ## TypeORM
103
+
104
+ `useTypeORM` initializes the DataSource, so it returns a promise:
105
+
106
+ ```typescript
107
+ await app.useTypeORM({
108
+ type: "postgres",
109
+ host: "localhost",
110
+ port: 5432,
111
+ username: "postgres",
112
+ password: "password",
113
+ database: "avleon",
114
+ entities: [User],
115
+ synchronize: true,
116
+ });
117
+ ```
118
+
119
+ Using a config class:
120
+
121
+ ```typescript
122
+ import { AppConfig, AvleonConfig, Environment } from "@avleon/core";
123
+ import type { DataSourceOptions } from "typeorm";
124
+
125
+ @AppConfig
126
+ export class DataSourceConfig extends AvleonConfig<DataSourceOptions> {
127
+ config(env: Environment): DataSourceOptions {
128
+ return {
129
+ type: "postgres",
130
+ host: env.get("DB_HOST") || "localhost",
131
+ port: Number(env.get("DB_PORT")) || 5432,
132
+ username: env.get("DB_USER") || "postgres",
133
+ password: env.get("DB_PASS") || "password",
134
+ database: env.get("DB_NAME") || "avleon",
135
+ entities: [User],
136
+ synchronize: true,
137
+ };
138
+ }
139
+ }
140
+
141
+ await app.useTypeORM(DataSourceConfig);
142
+ ```
143
+
144
+ **Injecting a repository.** `@InjectRepository` gives you the TypeORM repository
145
+ plus a `paginate()` method:
146
+
147
+ ```typescript
148
+ import { AppService } from "@avleon/core";
149
+ import { InjectRepository, PaginatedRepository } from "@avleon/data";
150
+ import { User } from "./user.entity";
151
+
152
+ @AppService
153
+ export class UserService {
154
+ constructor(
155
+ @InjectRepository(User)
156
+ private readonly userRepo: PaginatedRepository<User>,
157
+ ) {}
158
+
159
+ findAll() {
160
+ return this.userRepo.find();
161
+ }
162
+
163
+ page(page: number) {
164
+ return this.userRepo.paginate({ page, perPage: 20 });
165
+ }
166
+ }
167
+ ```
168
+
169
+ **Custom repositories.** Extend `AvleonRepository` for pagination, transactions
170
+ and your own query methods. Query operators (`Like`, `In`, `Not`, `Between`,
171
+ `IsNull`, `Equal`, `ArrayContains`, …) are exported from `@avleon/data`.
172
+
173
+ In 0.3.0, give the class an explicit constructor that calls `super()`, even if
174
+ it has no dependencies (see [Known Issues](#known-issues-in-030)):
175
+
176
+ ```typescript
177
+ import { AvleonRepository, Repository, Like } from "@avleon/data";
178
+
179
+ @Repository(User)
180
+ export class UserRepository extends AvleonRepository<User> {
181
+ constructor(private readonly audit: AuditService) {
182
+ super();
183
+ }
184
+
185
+ search(term: string, page = 1) {
186
+ return this.paginate(
187
+ { where: { name: Like(`%${term}%`) } },
188
+ { page, perPage: 20 },
189
+ );
190
+ }
191
+
192
+ async rename(id: number, name: string) {
193
+ return this.transaction(async (tx) => {
194
+ await tx.update({ id }, { name });
195
+ await this.audit.log("rename", id);
196
+ });
197
+ }
198
+ }
199
+ ```
200
+
201
+ `transaction()` joins an already active transaction instead of opening a nested
202
+ one. `withManager(manager)` returns a copy of the repository bound to another
203
+ `EntityManager`.
204
+
205
+ ## Pagination
206
+
207
+ `repo.paginate()`, `AvleonRepository.paginate()`, `KnexDB.paginate()` and
208
+ `paginateKnex()` return core's unified `{ data, meta }` shape; see
209
+ [Pagination](https://github.com/avleonjs/avleon/tree/main/packages/core#pagination).
210
+
211
+ ## License
212
+
213
+ MIT
@@ -0,0 +1,20 @@
1
+ import type { DataSource } from "typeorm";
2
+ /**
3
+ * String token under which the TypeORM `DataSource` is registered. Used by
4
+ * `paginatedRepository` and `@InjectRepository`.
5
+ */
6
+ export declare const DATASOURCE_TOKEN = "idatasource";
7
+ /**
8
+ * Register the application's TypeORM `DataSource` with the DI container.
9
+ *
10
+ * Sets both the `"idatasource"` string token and the `DataSource` class token
11
+ * (the class the instance was built from, and the consumer's `typeorm`
12
+ * `DataSource` export if that differs), so `@Repository`, `@InjectRepository`,
13
+ * `paginatedRepository` and `Container.get(DataSource)` all resolve it.
14
+ */
15
+ export declare function registerDataSource(dataSource: DataSource): DataSource;
16
+ /**
17
+ * Resolve the registered TypeORM `DataSource`, or throw a clear error if the
18
+ * application has not called `useTypeORM` (or `registerDataSource`) yet.
19
+ */
20
+ export declare function getDataSource(): DataSource;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DATASOURCE_TOKEN = void 0;
4
+ exports.registerDataSource = registerDataSource;
5
+ exports.getDataSource = getDataSource;
6
+ /**
7
+ * @copyright 2024
8
+ * @author Tareq Hossain
9
+ * @email xtrinsic96@gmail.com
10
+ * @url https://github.com/xtareq
11
+ */
12
+ const core_1 = require("@avleon/core");
13
+ /**
14
+ * String token under which the TypeORM `DataSource` is registered. Used by
15
+ * `paginatedRepository` and `@InjectRepository`.
16
+ */
17
+ exports.DATASOURCE_TOKEN = "idatasource";
18
+ /**
19
+ * Register the application's TypeORM `DataSource` with the DI container.
20
+ *
21
+ * Sets both the `"idatasource"` string token and the `DataSource` class token
22
+ * (the class the instance was built from, and the consumer's `typeorm`
23
+ * `DataSource` export if that differs), so `@Repository`, `@InjectRepository`,
24
+ * `paginatedRepository` and `Container.get(DataSource)` all resolve it.
25
+ */
26
+ function registerDataSource(dataSource) {
27
+ if (!dataSource) {
28
+ throw new Error("[Avleon] registerDataSource() requires a DataSource instance.");
29
+ }
30
+ core_1.AvleonContainer.set(exports.DATASOURCE_TOKEN, dataSource);
31
+ const ctor = dataSource.constructor;
32
+ if (typeof ctor === "function" && ctor !== Object) {
33
+ core_1.AvleonContainer.set(ctor, dataSource);
34
+ }
35
+ try {
36
+ const typeorm = (0, core_1.loadPackageFromClient)("typeorm");
37
+ if (typeorm?.DataSource && typeorm.DataSource !== ctor) {
38
+ core_1.AvleonContainer.set(typeorm.DataSource, dataSource);
39
+ }
40
+ }
41
+ catch {
42
+ // typeorm not resolvable from the app root; the constructor token is enough.
43
+ }
44
+ return dataSource;
45
+ }
46
+ /**
47
+ * Resolve the registered TypeORM `DataSource`, or throw a clear error if the
48
+ * application has not called `useTypeORM` (or `registerDataSource`) yet.
49
+ */
50
+ function getDataSource() {
51
+ if (core_1.AvleonContainer.has(exports.DATASOURCE_TOKEN)) {
52
+ return core_1.AvleonContainer.get(exports.DATASOURCE_TOKEN);
53
+ }
54
+ try {
55
+ const typeorm = (0, core_1.loadPackageFromClient)("typeorm");
56
+ if (core_1.AvleonContainer.has(typeorm.DataSource)) {
57
+ return core_1.AvleonContainer.get(typeorm.DataSource);
58
+ }
59
+ }
60
+ catch {
61
+ // fall through to the error below
62
+ }
63
+ throw new Error("[Avleon] No TypeORM DataSource is registered. Call app.useTypeORM(...) " +
64
+ "(or registerDataSource(dataSource)) before resolving repositories.");
65
+ }
66
+ //# sourceMappingURL=datasource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datasource.js","sourceRoot":"","sources":["../src/datasource.ts"],"names":[],"mappings":";;;AAuBA,gDAwBC;AAMD,sCAkBC;AAvED;;;;;GAKG;AACH,uCAAmF;AAGnF;;;GAGG;AACU,QAAA,gBAAgB,GAAG,aAAa,CAAC;AAE9C;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,UAAsB;IACvD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;IACJ,CAAC;IAED,sBAAS,CAAC,GAAG,CAAC,wBAAgB,EAAE,UAAU,CAAC,CAAC;IAE5C,MAAM,IAAI,GAAI,UAAkB,CAAC,WAAW,CAAC;IAC7C,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAClD,sBAAS,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,4BAAqB,EAA2B,SAAS,CAAC,CAAC;QAC3E,IAAI,OAAO,EAAE,UAAU,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YACvD,sBAAS,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa;IAC3B,IAAI,sBAAS,CAAC,GAAG,CAAC,wBAAgB,CAAC,EAAE,CAAC;QACpC,OAAO,sBAAS,CAAC,GAAG,CAAa,wBAAgB,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,4BAAqB,EAA2B,SAAS,CAAC,CAAC;QAC3E,IAAI,sBAAS,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,OAAO,sBAAS,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,yEAAyE;QACvE,oEAAoE,CACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./datasource";
2
+ export * from "./typeorm-provider";
3
+ export * from "./knex-provider";
4
+ export * from "./repository";
5
+ export { dataPlugin } from "./plugin";
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.dataPlugin = void 0;
18
+ __exportStar(require("./datasource"), exports);
19
+ __exportStar(require("./typeorm-provider"), exports);
20
+ __exportStar(require("./knex-provider"), exports);
21
+ __exportStar(require("./repository"), exports);
22
+ var plugin_1 = require("./plugin");
23
+ Object.defineProperty(exports, "dataPlugin", { enumerable: true, get: function () { return plugin_1.dataPlugin; } });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,qDAAmC;AACnC,kDAAgC;AAChC,+CAA6B;AAC7B,mCAAsC;AAA7B,oGAAA,UAAU,OAAA"}
@@ -0,0 +1,28 @@
1
+ import { Token, type PageRequest, type Paginated } from "@avleon/core";
2
+ import type { Knex } from "knex";
3
+ /** DI token holding the initialized Knex instance. Set by `app.useKnex(...)`. */
4
+ export declare const AVLEON_KNEX_DB: Token<Knex<any, any[]>>;
5
+ /**
6
+ * Injectable accessor for the application's Knex connection.
7
+ *
8
+ * The connection itself is created by `app.useKnex(...)`, which registers it
9
+ * under {@link AVLEON_KNEX_DB}. Resolving this service before that call throws.
10
+ */
11
+ export declare class KnexDB {
12
+ private readonly connection;
13
+ constructor();
14
+ get client(): Knex;
15
+ /**
16
+ * Run `query` for one page, returning the unified pagination shape.
17
+ *
18
+ * ```ts
19
+ * const { data, meta } = await db.paginate(db.client("users").where("active", true), { page: 2 });
20
+ * ```
21
+ *
22
+ * The total is counted on a clone of the query with its select, order and
23
+ * limit/offset cleared.
24
+ */
25
+ paginate<T = any>(query: Knex.QueryBuilder, options?: PageRequest): Promise<Paginated<T>>;
26
+ }
27
+ /** Paginate any Knex query builder into the unified `{ data, meta }` shape. */
28
+ export declare function paginateKnex<T = any>(query: Knex.QueryBuilder, options?: PageRequest): Promise<Paginated<T>>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.KnexDB = exports.AVLEON_KNEX_DB = void 0;
13
+ exports.paginateKnex = paginateKnex;
14
+ const core_1 = require("@avleon/core");
15
+ /** DI token holding the initialized Knex instance. Set by `app.useKnex(...)`. */
16
+ exports.AVLEON_KNEX_DB = new core_1.Token("AVLEON_KNEX_DB");
17
+ /**
18
+ * Injectable accessor for the application's Knex connection.
19
+ *
20
+ * The connection itself is created by `app.useKnex(...)`, which registers it
21
+ * under {@link AVLEON_KNEX_DB}. Resolving this service before that call throws.
22
+ */
23
+ let KnexDB = class KnexDB {
24
+ connection;
25
+ constructor() {
26
+ const existing = core_1.AvleonContainer.has(exports.AVLEON_KNEX_DB)
27
+ ? core_1.AvleonContainer.get(exports.AVLEON_KNEX_DB)
28
+ : null;
29
+ if (!existing) {
30
+ throw new Error("Knex is not initialized. Call useKnex first.");
31
+ }
32
+ this.connection = existing;
33
+ }
34
+ get client() {
35
+ return this.connection;
36
+ }
37
+ /**
38
+ * Run `query` for one page, returning the unified pagination shape.
39
+ *
40
+ * ```ts
41
+ * const { data, meta } = await db.paginate(db.client("users").where("active", true), { page: 2 });
42
+ * ```
43
+ *
44
+ * The total is counted on a clone of the query with its select, order and
45
+ * limit/offset cleared.
46
+ */
47
+ async paginate(query, options) {
48
+ return paginateKnex(query, options);
49
+ }
50
+ };
51
+ exports.KnexDB = KnexDB;
52
+ exports.KnexDB = KnexDB = __decorate([
53
+ (0, core_1.Injectable)(),
54
+ __metadata("design:paramtypes", [])
55
+ ], KnexDB);
56
+ /** Paginate any Knex query builder into the unified `{ data, meta }` shape. */
57
+ async function paginateKnex(query, options) {
58
+ const { page, perPage, offset } = (0, core_1.normalizePageRequest)(options);
59
+ const countRow = await query
60
+ .clone()
61
+ .clearSelect()
62
+ .clearOrder()
63
+ .clear("limit")
64
+ .clear("offset")
65
+ .count({ total: "*" })
66
+ .first();
67
+ const total = Number(countRow?.total ?? 0);
68
+ const data = (await query.clone().offset(offset).limit(perPage));
69
+ return (0, core_1.paginated)(data, total, page, perPage);
70
+ }
71
+ //# sourceMappingURL=knex-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knex-provider.js","sourceRoot":"","sources":["../src/knex-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;AA2DA,oCAkBC;AA7ED,uCAQsB;AAGtB,iFAAiF;AACpE,QAAA,cAAc,GAAG,IAAI,YAAK,CAAO,gBAAgB,CAAC,CAAC;AAEhE;;;;;GAKG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IACA,UAAU,CAAO;IAElC;QACE,MAAM,QAAQ,GAAG,sBAAS,CAAC,GAAG,CAAC,sBAAc,CAAC;YAC5C,CAAC,CAAC,sBAAS,CAAC,GAAG,CAAO,sBAAc,CAAC;YACrC,CAAC,CAAC,IAAI,CAAC;QAET,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,QAAQ,CACZ,KAAwB,EACxB,OAAqB;QAErB,OAAO,YAAY,CAAI,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;CACF,CAAA;AAnCY,wBAAM;iBAAN,MAAM;IADlB,IAAA,iBAAU,GAAE;;GACA,MAAM,CAmClB;AAED,+EAA+E;AACxE,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,OAAqB;IAErB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAQ,MAAM,KAAK;SAC9B,KAAK,EAAE;SACP,WAAW,EAAE;SACb,UAAU,EAAE;SACZ,KAAK,CAAC,OAAc,CAAC;SACrB,KAAK,CAAC,QAAe,CAAC;SACtB,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;SACrB,KAAK,EAAE,CAAC;IACX,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAQ,CAAC;IACxE,OAAO,IAAA,gBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type AvleonConfigClass } from "@avleon/core";
2
+ import type { Knex } from "knex";
3
+ import type { DataSourceOptions } from "typeorm";
4
+ declare module "@avleon/core" {
5
+ interface AvleonApplication {
6
+ /**
7
+ * Connect Knex from a config object or an `@AppConfig` class, and register
8
+ * it for `KnexDB`. Resolves once a test query succeeds. The connection is
9
+ * destroyed when the app shuts down.
10
+ */
11
+ useKnex(options: Knex.Config | AvleonConfigClass<Knex.Config>): Promise<this>;
12
+ /**
13
+ * Initialize a TypeORM DataSource from its options or an `@AppConfig`
14
+ * class, and register it for repositories. Resolves once connected. The
15
+ * DataSource is destroyed when the app shuts down.
16
+ */
17
+ useTypeORM(options: DataSourceOptions | AvleonConfigClass<DataSourceOptions>): Promise<this>;
18
+ }
19
+ }
20
+ export declare const dataPlugin: import("@avleon/core").AvleonPlugin;
21
+ export default dataPlugin;
package/dist/plugin.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dataPlugin = void 0;
4
+ const core_1 = require("@avleon/core");
5
+ const datasource_1 = require("./datasource");
6
+ const knex_provider_1 = require("./knex-provider");
7
+ /** Options given directly, or built by an `@AppConfig` class from the environment. */
8
+ function resolveOptions(ctx, options) {
9
+ if (typeof options === "function" && options.prototype instanceof core_1.AvleonConfig) {
10
+ const config = ctx.container.get(options);
11
+ return config.config(ctx.container.get(core_1.Environment));
12
+ }
13
+ return options;
14
+ }
15
+ exports.dataPlugin = (0, core_1.definePlugin)({
16
+ name: "@avleon/data",
17
+ register(ctx) {
18
+ ctx.extend("useKnex", async (options) => {
19
+ const knex = (0, core_1.loadPackageFromClient)("knex");
20
+ const config = resolveOptions(ctx, options);
21
+ // Fail early with an install hint if the driver is missing.
22
+ if (typeof config?.client === "string")
23
+ (0, core_1.loadPackageFromClient)(config.client);
24
+ const db = knex(config);
25
+ ctx.container.set(knex_provider_1.AVLEON_KNEX_DB, db);
26
+ await db.raw("SELECT 1");
27
+ ctx.onClose(() => db.destroy());
28
+ return ctx.app;
29
+ });
30
+ ctx.extend("useTypeORM", async (options) => {
31
+ const typeorm = (0, core_1.loadPackageFromClient)("typeorm");
32
+ const dataSource = (0, datasource_1.registerDataSource)(new typeorm.DataSource(resolveOptions(ctx, options)));
33
+ try {
34
+ await dataSource.initialize();
35
+ }
36
+ catch (error) {
37
+ ctx.logger.error({ err: error }, "Database connection failed");
38
+ throw error;
39
+ }
40
+ ctx.logger.info("Database connected");
41
+ ctx.onClose(() => dataSource.destroy());
42
+ return ctx.app;
43
+ });
44
+ },
45
+ });
46
+ exports.default = exports.dataPlugin;
47
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":";;;AAAA,uCAOsB;AAGtB,6CAAkD;AAClD,mDAAiD;AAqBjD,sFAAsF;AACtF,SAAS,cAAc,CAAI,GAAkB,EAAE,OAAiC;IAC9E,IAAI,OAAO,OAAO,KAAK,UAAU,IAAI,OAAO,CAAC,SAAS,YAAY,mBAAY,EAAE,CAAC;QAC/E,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAkB,OAA+B,CAAC,CAAC;QACnF,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAW,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,OAAY,CAAC;AACtB,CAAC;AAEY,QAAA,UAAU,GAAG,IAAA,mBAAY,EAAC;IACrC,IAAI,EAAE,cAAc;IACpB,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,OAAqD,EAAE,EAAE;YACpF,MAAM,IAAI,GAAG,IAAA,4BAAqB,EAAwB,MAAM,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC5C,4DAA4D;YAC5D,IAAI,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ;gBAAE,IAAA,4BAAqB,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAE7E,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,8BAAc,EAAE,EAAE,CAAC,CAAC;YACtC,MAAM,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACzB,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAChC,OAAO,GAAG,CAAC,GAAG,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,MAAM,CACR,YAAY,EACZ,KAAK,EAAE,OAAiE,EAAE,EAAE;YAC1E,MAAM,OAAO,GAAG,IAAA,4BAAqB,EAA2B,SAAS,CAAC,CAAC;YAC3E,MAAM,UAAU,GAAG,IAAA,+BAAkB,EACnC,IAAI,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CACrD,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,4BAA4B,CAAC,CAAC;gBAC/D,MAAM,KAAK,CAAC;YACd,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;YACxC,OAAO,GAAG,CAAC,GAAG,CAAC;QACjB,CAAC,CACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,kBAAe,kBAAU,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type PageRequest, type Paginated } from "@avleon/core";
2
+ import type { EntityTarget, ObjectLiteral, Repository } from "typeorm";
3
+ /** A TypeORM repository extended with the unified `paginate`. */
4
+ export type PaginatedRepository<T extends ObjectLiteral> = Repository<T> & {
5
+ paginate(options?: PageRequest): Promise<Paginated<T>>;
6
+ };
7
+ /**
8
+ * The TypeORM repository for `entity`, from the registered DataSource, with
9
+ * the unified `paginate({ page, perPage })` added.
10
+ */
11
+ export declare function paginatedRepository<T extends ObjectLiteral>(entity: EntityTarget<T>, dataSource?: import("typeorm").DataSource): PaginatedRepository<T>;
12
+ /**
13
+ * Inject the TypeORM repository for `model`, extended with the unified
14
+ * `paginate({ page, perPage })`. Requires a registered DataSource.
15
+ */
16
+ export declare function InjectRepository<T extends ObjectLiteral>(model: EntityTarget<T>): (object: any, propertyName: string | symbol | undefined, index?: number) => void;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.paginatedRepository = paginatedRepository;
4
+ exports.InjectRepository = InjectRepository;
5
+ const core_1 = require("@avleon/core");
6
+ const datasource_1 = require("./datasource");
7
+ async function paginateRepository(repo, options) {
8
+ const { page, perPage, offset } = (0, core_1.normalizePageRequest)(options);
9
+ const [data, total] = await repo.findAndCount({
10
+ skip: offset,
11
+ take: perPage,
12
+ });
13
+ return (0, core_1.paginated)(data, total, page, perPage);
14
+ }
15
+ /**
16
+ * The TypeORM repository for `entity`, from the registered DataSource, with
17
+ * the unified `paginate({ page, perPage })` added.
18
+ */
19
+ function paginatedRepository(entity, dataSource = (0, datasource_1.getDataSource)()) {
20
+ return dataSource.getRepository(entity).extend({
21
+ paginate(options) {
22
+ return paginateRepository(this, options);
23
+ },
24
+ });
25
+ }
26
+ /**
27
+ * Inject the TypeORM repository for `model`, extended with the unified
28
+ * `paginate({ page, perPage })`. Requires a registered DataSource.
29
+ */
30
+ function InjectRepository(model) {
31
+ return (0, core_1.createInjectDecorator)(() => paginatedRepository(model));
32
+ }
33
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":";;AA+BA,kDASC;AAMD,4CAIC;AAlDD,uCAMsB;AAEtB,6CAA6C;AAO7C,KAAK,UAAU,kBAAkB,CAC/B,IAAmB,EACnB,OAAqB;IAErB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAA,2BAAoB,EAAC,OAAO,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC;QAC5C,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IACH,OAAO,IAAA,gBAAS,EAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CACjC,MAAuB,EACvB,UAAU,GAAG,IAAA,0BAAa,GAAE;IAE5B,OAAO,UAAU,CAAC,aAAa,CAAI,MAAM,CAAC,CAAC,MAAM,CAAC;QAChD,QAAQ,CAAsB,OAAqB;YACjD,OAAO,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;KACF,CAA2B,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,KAAsB;IAEtB,OAAO,IAAA,4BAAqB,EAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,120 @@
1
+ import type { EntityManager, EntityTarget, FindManyOptions, FindOneOptions, FindOptionsWhere, DeepPartial, Repository as OrmRepository, ObjectLiteral, SelectQueryBuilder, QueryRunner, InsertResult, UpdateResult, DeleteResult, ObjectId, SaveOptions, RemoveOptions, EntityMetadata } from "typeorm";
2
+ import { type Constructor, type PageRequest, type Paginated } from "@avleon/core";
3
+ export declare const Like: typeof import("typeorm").Like;
4
+ export declare const ILike: typeof import("typeorm").ILike;
5
+ export declare const In: typeof import("typeorm").In;
6
+ export declare const Not: typeof import("typeorm").Not;
7
+ export declare const Between: typeof import("typeorm").Between;
8
+ export declare const LessThan: typeof import("typeorm").LessThan;
9
+ export declare const LessThanOrEqual: typeof import("typeorm").LessThanOrEqual;
10
+ export declare const MoreThan: typeof import("typeorm").MoreThan;
11
+ export declare const MoreThanOrEqual: typeof import("typeorm").MoreThanOrEqual;
12
+ export declare const IsNull: typeof import("typeorm").IsNull;
13
+ export declare const Any: typeof import("typeorm").Any;
14
+ export declare const Raw: typeof import("typeorm").Raw;
15
+ export declare const Equal: typeof import("typeorm").Equal;
16
+ export declare const ArrayContains: typeof import("typeorm").ArrayContains;
17
+ /** @deprecated Use {@link PageRequest} (`{ page, perPage }`). */
18
+ export interface PaginationOptions {
19
+ page: number;
20
+ limit: number;
21
+ }
22
+ /** @deprecated Use {@link Paginated}. Kept as an alias of the unified shape. */
23
+ export type PaginatedResult<T> = Paginated<T>;
24
+ export interface SoftDeletable {
25
+ deletedAt?: Date | null;
26
+ }
27
+ export declare class AvleonRepository<TEntity extends ObjectLiteral> {
28
+ protected orm: OrmRepository<TEntity>;
29
+ protected entity: EntityTarget<TEntity>;
30
+ protected manager: EntityManager;
31
+ /**
32
+ * Both arguments are optional for `@Repository(Entity)` classes: the entity
33
+ * comes from the decorator and the manager from the registered DataSource,
34
+ * so a subclass constructor can take its own injected dependencies and
35
+ * call `super()` with no arguments.
36
+ */
37
+ constructor(entity?: EntityTarget<TEntity>, manager?: EntityManager);
38
+ get metadata(): EntityMetadata;
39
+ get target(): EntityTarget<TEntity>;
40
+ find(options?: FindManyOptions<TEntity>): Promise<TEntity[]>;
41
+ findOne(options: FindOneOptions<TEntity>): Promise<TEntity | null>;
42
+ findOneBy(where: FindOptionsWhere<TEntity> | FindOptionsWhere<TEntity>[]): Promise<TEntity | null>;
43
+ findBy(where: FindOptionsWhere<TEntity> | FindOptionsWhere<TEntity>[]): Promise<TEntity[]>;
44
+ findById(id: number | string | ObjectId): Promise<TEntity | null>;
45
+ findByIds(ids: (number | string | ObjectId)[]): Promise<TEntity[]>;
46
+ findAndCount(options?: FindManyOptions<TEntity>): Promise<[TEntity[], number]>;
47
+ findAndCountBy(where: FindOptionsWhere<TEntity> | FindOptionsWhere<TEntity>[]): Promise<[TEntity[], number]>;
48
+ count(options?: FindManyOptions<TEntity>): Promise<number>;
49
+ countBy(where: FindOptionsWhere<TEntity> | FindOptionsWhere<TEntity>[]): Promise<number>;
50
+ exists(options?: FindManyOptions<TEntity>): Promise<boolean>;
51
+ existsBy(where: FindOptionsWhere<TEntity> | FindOptionsWhere<TEntity>[]): Promise<boolean>;
52
+ /**
53
+ * Fetch one page of entities.
54
+ *
55
+ * ```ts
56
+ * const { data, meta } = await repo.paginate({ where: { active: true } }, { page: 2, perPage: 20 });
57
+ * ```
58
+ */
59
+ paginate(options?: FindManyOptions<TEntity>, pagination?: PageRequest): Promise<Paginated<TEntity>>;
60
+ create(data?: DeepPartial<TEntity>): TEntity[];
61
+ createMany(dataArray: DeepPartial<TEntity>[]): TEntity[][];
62
+ save(data: DeepPartial<TEntity>, options?: SaveOptions): Promise<TEntity>;
63
+ saveMany(dataArray: DeepPartial<TEntity>[], options?: SaveOptions): Promise<TEntity[]>;
64
+ insert(data: DeepPartial<TEntity> | DeepPartial<TEntity>[]): Promise<InsertResult>;
65
+ upsert(data: DeepPartial<TEntity> | DeepPartial<TEntity>[], conflictPaths: string[] | any): Promise<InsertResult>;
66
+ update(criteria: string | string[] | number | number[] | FindOptionsWhere<TEntity>, data: DeepPartial<TEntity>): Promise<UpdateResult>;
67
+ updateById(id: number | string, data: DeepPartial<TEntity>): Promise<UpdateResult>;
68
+ delete(criteria: string | string[] | number | number[] | FindOptionsWhere<TEntity>): Promise<DeleteResult>;
69
+ deleteById(id: number | string): Promise<DeleteResult>;
70
+ remove(entity: TEntity, options?: RemoveOptions): Promise<TEntity>;
71
+ removeMany(entities: TEntity[], options?: RemoveOptions): Promise<TEntity[]>;
72
+ softDelete(criteria: string | string[] | number | number[] | FindOptionsWhere<TEntity>): Promise<UpdateResult>;
73
+ softDeleteById(id: number | string): Promise<UpdateResult>;
74
+ restore(criteria: string | string[] | number | number[] | FindOptionsWhere<TEntity>): Promise<UpdateResult>;
75
+ softRemove(entity: TEntity, options?: SaveOptions): Promise<TEntity>;
76
+ sum(column: keyof TEntity, where?: FindOptionsWhere<TEntity>): Promise<number | null>;
77
+ avg(column: keyof TEntity, where?: FindOptionsWhere<TEntity>): Promise<number | null>;
78
+ min(column: keyof TEntity, where?: FindOptionsWhere<TEntity>): Promise<number | null>;
79
+ max(column: keyof TEntity, where?: FindOptionsWhere<TEntity>): Promise<number | null>;
80
+ /**
81
+ * Run a callback inside a transaction. If the callback throws,
82
+ * the transaction is rolled back automatically.
83
+ */
84
+ transaction<T>(work: (repo: this, queryRunner: QueryRunner) => Promise<T>): Promise<T>;
85
+ /**
86
+ * A copy of this repository bound to another `EntityManager` (for example a
87
+ * transaction's). The copy keeps every injected dependency of the original;
88
+ * no constructor runs.
89
+ */
90
+ withManager(manager: EntityManager): this;
91
+ /** Create a QueryBuilder with a default alias of the entity table name. */
92
+ qb(alias?: string): SelectQueryBuilder<TEntity>;
93
+ /**
94
+ * Efficient bulk insert using chunking to avoid hitting SQL parameter limits.
95
+ */
96
+ bulkInsert(rows: DeepPartial<TEntity>[], chunkSize?: number): Promise<void>;
97
+ /**
98
+ * Execute raw SQL. Use sparingly — prefer the query builder.
99
+ * @param sql Parameterised SQL string
100
+ * @param params Positional parameters
101
+ */
102
+ raw<T = any>(sql: string, params?: any[]): Promise<T[]>;
103
+ protected getRepository(): OrmRepository<TEntity>;
104
+ protected getManager(): EntityManager;
105
+ }
106
+ /**
107
+ * Class decorator that registers a repository with the DI container and binds
108
+ * it to `entity`. The DataSource is resolved from the container when the
109
+ * repository is constructed.
110
+ *
111
+ * The class keeps its own constructor, so it can inject other services:
112
+ *
113
+ * ```ts
114
+ * @Repository(User)
115
+ * class UserRepository extends AvleonRepository<User> {
116
+ * constructor(private readonly audit: AuditService) { super(); }
117
+ * }
118
+ * ```
119
+ */
120
+ export declare function Repository<TEntity extends ObjectLiteral>(entity: EntityTarget<TEntity>): <TBase extends Constructor<AvleonRepository<TEntity>>>(Base: TBase) => TBase;
@@ -0,0 +1,303 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AvleonRepository = exports.ArrayContains = exports.Equal = exports.Raw = exports.Any = exports.IsNull = exports.MoreThanOrEqual = exports.MoreThan = exports.LessThanOrEqual = exports.LessThan = exports.Between = exports.Not = exports.In = exports.ILike = exports.Like = void 0;
4
+ exports.Repository = Repository;
5
+ const core_1 = require("@avleon/core");
6
+ const datasource_1 = require("./datasource");
7
+ function typeormOperator(name) {
8
+ return ((...args) => {
9
+ const typeorm = (0, core_1.loadPackageFromClient)("typeorm");
10
+ return typeorm[name](...args);
11
+ });
12
+ }
13
+ exports.Like = typeormOperator("Like");
14
+ exports.ILike = typeormOperator("ILike");
15
+ exports.In = typeormOperator("In");
16
+ exports.Not = typeormOperator("Not");
17
+ exports.Between = typeormOperator("Between");
18
+ exports.LessThan = typeormOperator("LessThan");
19
+ exports.LessThanOrEqual = typeormOperator("LessThanOrEqual");
20
+ exports.MoreThan = typeormOperator("MoreThan");
21
+ exports.MoreThanOrEqual = typeormOperator("MoreThanOrEqual");
22
+ exports.IsNull = typeormOperator("IsNull");
23
+ exports.Any = typeormOperator("Any");
24
+ exports.Raw = typeormOperator("Raw");
25
+ exports.Equal = typeormOperator("Equal");
26
+ exports.ArrayContains = typeormOperator("ArrayContains");
27
+ // ─── Base Repository ─────────────────────────────────────────────────────────
28
+ const REPOSITORY_ENTITY = Symbol.for("avleon:repository:entity");
29
+ class AvleonRepository {
30
+ orm;
31
+ entity;
32
+ manager;
33
+ /**
34
+ * Both arguments are optional for `@Repository(Entity)` classes: the entity
35
+ * comes from the decorator and the manager from the registered DataSource,
36
+ * so a subclass constructor can take its own injected dependencies and
37
+ * call `super()` with no arguments.
38
+ */
39
+ constructor(entity, manager) {
40
+ const resolvedEntity = entity ??
41
+ this.constructor[REPOSITORY_ENTITY];
42
+ if (!resolvedEntity) {
43
+ throw new Error(`[Avleon] ${this.constructor.name} has no entity. Decorate it with @Repository(Entity) or pass the entity to super().`);
44
+ }
45
+ this.entity = resolvedEntity;
46
+ this.manager = manager ?? (0, datasource_1.getDataSource)().manager;
47
+ this.orm = this.manager.getRepository(this.entity);
48
+ }
49
+ // ─── Metadata ────────────────────────────────────────────────────────────
50
+ get metadata() {
51
+ return this.orm.metadata;
52
+ }
53
+ get target() {
54
+ return this.entity;
55
+ }
56
+ // ─── Basic CRUD ──────────────────────────────────────────────────────────
57
+ find(options) {
58
+ return this.orm.find(options);
59
+ }
60
+ findOne(options) {
61
+ return this.orm.findOne(options);
62
+ }
63
+ findOneBy(where) {
64
+ return this.orm.findOneBy(where);
65
+ }
66
+ findBy(where) {
67
+ return this.orm.findBy(where);
68
+ }
69
+ findById(id) {
70
+ return this.orm.findOne({ where: { id } });
71
+ }
72
+ findByIds(ids) {
73
+ return this.orm.findBy({ id: (0, exports.In)(ids) });
74
+ }
75
+ findAndCount(options) {
76
+ return this.orm.findAndCount(options);
77
+ }
78
+ findAndCountBy(where) {
79
+ return this.orm.findAndCountBy(where);
80
+ }
81
+ count(options) {
82
+ return this.orm.count(options);
83
+ }
84
+ countBy(where) {
85
+ return this.orm.countBy(where);
86
+ }
87
+ exists(options) {
88
+ return this.orm.exists(options);
89
+ }
90
+ existsBy(where) {
91
+ return this.orm.existsBy(where);
92
+ }
93
+ // ─── Pagination ──────────────────────────────────────────────────────────
94
+ /**
95
+ * Fetch one page of entities.
96
+ *
97
+ * ```ts
98
+ * const { data, meta } = await repo.paginate({ where: { active: true } }, { page: 2, perPage: 20 });
99
+ * ```
100
+ */
101
+ async paginate(options = {}, pagination = {}) {
102
+ const { page, perPage, offset } = (0, core_1.normalizePageRequest)(pagination);
103
+ const [data, total] = await this.orm.findAndCount({
104
+ ...options,
105
+ skip: offset,
106
+ take: perPage,
107
+ });
108
+ return (0, core_1.paginated)(data, total, page, perPage);
109
+ }
110
+ // ─── Create & Save ───────────────────────────────────────────────────────
111
+ create(data) {
112
+ return this.orm.create(data);
113
+ }
114
+ createMany(dataArray) {
115
+ return dataArray.map((d) => this.orm.create(d));
116
+ }
117
+ async save(data, options) {
118
+ return this.orm.save(data, options);
119
+ }
120
+ async saveMany(dataArray, options) {
121
+ return this.orm.save(dataArray, options);
122
+ }
123
+ // ─── Insert ──────────────────────────────────────────────────────────────
124
+ async insert(data) {
125
+ return this.orm.insert(data);
126
+ }
127
+ // ─── Upsert ──────────────────────────────────────────────────────────────
128
+ async upsert(data, conflictPaths) {
129
+ return this.orm.upsert(data, conflictPaths);
130
+ }
131
+ // ─── Update ──────────────────────────────────────────────────────────────
132
+ async update(criteria, data) {
133
+ return this.orm.update(criteria, data);
134
+ }
135
+ async updateById(id, data) {
136
+ return this.orm.update(id, data);
137
+ }
138
+ // ─── Delete & Remove ─────────────────────────────────────────────────────
139
+ async delete(criteria) {
140
+ return this.orm.delete(criteria);
141
+ }
142
+ async deleteById(id) {
143
+ return this.orm.delete(id);
144
+ }
145
+ async remove(entity, options) {
146
+ return this.orm.remove(entity, options);
147
+ }
148
+ async removeMany(entities, options) {
149
+ return this.orm.remove(entities, options);
150
+ }
151
+ // ─── Soft Delete (requires @DeleteDateColumn) ────────────────────────────
152
+ async softDelete(criteria) {
153
+ return this.orm.softDelete(criteria);
154
+ }
155
+ async softDeleteById(id) {
156
+ return this.orm.softDelete(id);
157
+ }
158
+ async restore(criteria) {
159
+ return this.orm.restore(criteria);
160
+ }
161
+ async softRemove(entity, options) {
162
+ return this.orm.softRemove(entity, options);
163
+ }
164
+ // ─── Aggregation via Query Builder ───────────────────────────────────────
165
+ async sum(column, where) {
166
+ const alias = "e";
167
+ const qb = this.orm
168
+ .createQueryBuilder(alias)
169
+ .select(`SUM(${alias}.${String(column)})`, "sum");
170
+ if (where)
171
+ qb.where(where);
172
+ const result = await qb.getRawOne();
173
+ return result?.sum != null ? Number(result.sum) : null;
174
+ }
175
+ async avg(column, where) {
176
+ const alias = "e";
177
+ const qb = this.orm
178
+ .createQueryBuilder(alias)
179
+ .select(`AVG(${alias}.${String(column)})`, "avg");
180
+ if (where)
181
+ qb.where(where);
182
+ const result = await qb.getRawOne();
183
+ return result?.avg != null ? Number(result.avg) : null;
184
+ }
185
+ async min(column, where) {
186
+ const alias = "e";
187
+ const qb = this.orm
188
+ .createQueryBuilder(alias)
189
+ .select(`MIN(${alias}.${String(column)})`, "min");
190
+ if (where)
191
+ qb.where(where);
192
+ const result = await qb.getRawOne();
193
+ return result?.min != null ? Number(result.min) : null;
194
+ }
195
+ async max(column, where) {
196
+ const alias = "e";
197
+ const qb = this.orm
198
+ .createQueryBuilder(alias)
199
+ .select(`MAX(${alias}.${String(column)})`, "max");
200
+ if (where)
201
+ qb.where(where);
202
+ const result = await qb.getRawOne();
203
+ return result?.max != null ? Number(result.max) : null;
204
+ }
205
+ // ─── Transactions ────────────────────────────────────────────────────────
206
+ /**
207
+ * Run a callback inside a transaction. If the callback throws,
208
+ * the transaction is rolled back automatically.
209
+ */
210
+ async transaction(work) {
211
+ // Already inside a transaction: join it rather than opening a new one.
212
+ const current = this.manager.queryRunner;
213
+ if (current?.isTransactionActive) {
214
+ return work(this, current);
215
+ }
216
+ const queryRunner = this.manager.connection.createQueryRunner();
217
+ await queryRunner.connect();
218
+ await queryRunner.startTransaction();
219
+ const txRepo = this.withManager(queryRunner.manager);
220
+ try {
221
+ const result = await work(txRepo, queryRunner);
222
+ await queryRunner.commitTransaction();
223
+ return result;
224
+ }
225
+ catch (err) {
226
+ await queryRunner.rollbackTransaction();
227
+ throw err;
228
+ }
229
+ finally {
230
+ await queryRunner.release();
231
+ }
232
+ }
233
+ /**
234
+ * A copy of this repository bound to another `EntityManager` (for example a
235
+ * transaction's). The copy keeps every injected dependency of the original;
236
+ * no constructor runs.
237
+ */
238
+ withManager(manager) {
239
+ const copy = Object.create(Object.getPrototypeOf(this));
240
+ Object.assign(copy, this);
241
+ copy.manager = manager;
242
+ copy.orm = manager.getRepository(this.entity);
243
+ return copy;
244
+ }
245
+ // ─── Query Builder Access ────────────────────────────────────────────────
246
+ /** Create a QueryBuilder with a default alias of the entity table name. */
247
+ qb(alias) {
248
+ return this.orm.createQueryBuilder(alias ?? this.orm.metadata.tableName);
249
+ }
250
+ // ─── Bulk / Raw ──────────────────────────────────────────────────────────
251
+ /**
252
+ * Efficient bulk insert using chunking to avoid hitting SQL parameter limits.
253
+ */
254
+ async bulkInsert(rows, chunkSize = 500) {
255
+ for (let i = 0; i < rows.length; i += chunkSize) {
256
+ await this.orm.insert(rows.slice(i, i + chunkSize));
257
+ }
258
+ }
259
+ /**
260
+ * Execute raw SQL. Use sparingly — prefer the query builder.
261
+ * @param sql Parameterised SQL string
262
+ * @param params Positional parameters
263
+ */
264
+ async raw(sql, params) {
265
+ return this.manager.query(sql, params);
266
+ }
267
+ // ─── Protected helpers ───────────────────────────────────────────────────
268
+ getRepository() {
269
+ return this.orm;
270
+ }
271
+ getManager() {
272
+ return this.manager;
273
+ }
274
+ }
275
+ exports.AvleonRepository = AvleonRepository;
276
+ // ─── @Repository decorator ───────────────────────────────────────────────────
277
+ /**
278
+ * Class decorator that registers a repository with the DI container and binds
279
+ * it to `entity`. The DataSource is resolved from the container when the
280
+ * repository is constructed.
281
+ *
282
+ * The class keeps its own constructor, so it can inject other services:
283
+ *
284
+ * ```ts
285
+ * @Repository(User)
286
+ * class UserRepository extends AvleonRepository<User> {
287
+ * constructor(private readonly audit: AuditService) { super(); }
288
+ * }
289
+ * ```
290
+ */
291
+ function Repository(entity) {
292
+ return function (Base) {
293
+ Object.defineProperty(Base, REPOSITORY_ENTITY, {
294
+ value: entity,
295
+ enumerable: false,
296
+ configurable: true,
297
+ writable: true,
298
+ });
299
+ (0, core_1.Injectable)()(Base);
300
+ return Base;
301
+ };
302
+ }
303
+ //# sourceMappingURL=typeorm-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm-provider.js","sourceRoot":"","sources":["../src/typeorm-provider.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,100 @@
1
1
  {
2
2
  "name": "@avleon/data",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.0",
4
+ "description": "TypeORM and Knex integration for Avleon",
5
+ "author": "Tareq Hossain",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "require": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./plugin": {
16
+ "types": "./dist/plugin.d.ts",
17
+ "require": "./dist/plugin.js",
18
+ "default": "./dist/plugin.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
22
+ "avleon": {
23
+ "plugin": "./dist/plugin.js"
24
+ },
25
+ "engines": {
26
+ "node": ">=20.0.0"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "keywords": [
34
+ "avleon",
35
+ "typeorm",
36
+ "knex",
37
+ "database",
38
+ "typescript"
39
+ ],
40
+ "scripts": {
41
+ "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
42
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json",
43
+ "test": "vitest run",
44
+ "test:watch": "vitest",
45
+ "prepublishOnly": "npm run build"
46
+ },
47
+ "peerDependencies": {
48
+ "@avleon/core": "^0.4.0",
49
+ "better-sqlite3": ">=12.0.0",
50
+ "knex": ">=2.0.0",
51
+ "mssql": ">=11.0.0",
52
+ "mysql2": ">=3.0.0",
53
+ "pg": ">=8.0.0",
54
+ "sqlite3": ">=5.0.0",
55
+ "typeorm": ">=0.3.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "better-sqlite3": {
59
+ "optional": true
60
+ },
61
+ "knex": {
62
+ "optional": true
63
+ },
64
+ "mssql": {
65
+ "optional": true
66
+ },
67
+ "mysql2": {
68
+ "optional": true
69
+ },
70
+ "pg": {
71
+ "optional": true
72
+ },
73
+ "sqlite3": {
74
+ "optional": true
75
+ },
76
+ "typeorm": {
77
+ "optional": true
78
+ }
79
+ },
80
+ "devDependencies": {
81
+ "@avleon/core": "^0.4.0",
82
+ "@swc/core": "^1.16.20",
83
+ "@types/node": "^20.19.17",
84
+ "better-sqlite3": "^12.9.0",
85
+ "knex": "^3.1.0",
86
+ "reflect-metadata": "^0.2.2",
87
+ "typeorm": "^0.3.28",
88
+ "typescript": "^5.7.2",
89
+ "unplugin-swc": "^2.0.0",
90
+ "vitest": "^4.1.12"
91
+ },
92
+ "repository": {
93
+ "type": "git",
94
+ "url": "git+https://github.com/avleonjs/avleon.git",
95
+ "directory": "packages/data"
96
+ },
97
+ "publishConfig": {
98
+ "access": "public"
99
+ }
100
+ }