@decohere/data-typeorm 0.0.1-dev.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/commonjs/src/bootstrap-policy.js +69 -0
  2. package/commonjs/src/bootstrap.js +142 -0
  3. package/commonjs/src/data-source.factory.js +42 -0
  4. package/commonjs/src/database-options.js +4 -0
  5. package/commonjs/src/dialect-map.js +26 -0
  6. package/commonjs/src/index.js +24 -0
  7. package/commonjs/src/inject-data-source.js +33 -0
  8. package/commonjs/src/scripts/user.js +259 -0
  9. package/commonjs/src/server-manager.js +294 -0
  10. package/commonjs/src/sql-pretty.transport.js +35 -0
  11. package/commonjs/src/type-orm.module.js +115 -0
  12. package/commonjs/src/type-orm.provider.js +36 -0
  13. package/commonjs/src/type-orm.repository.js +30 -0
  14. package/commonjs/src/typeorm-scribe.logger.js +70 -0
  15. package/commonjs/src/typeorm.extensions.js +60 -0
  16. package/commonjs/src/unit-of-work.js +49 -0
  17. package/es6/src/bootstrap-policy.js +55 -0
  18. package/es6/src/bootstrap.js +139 -0
  19. package/es6/src/data-source.factory.js +27 -0
  20. package/es6/src/database-options.js +1 -0
  21. package/es6/src/dialect-map.js +8 -0
  22. package/es6/src/index.js +7 -0
  23. package/es6/src/inject-data-source.js +20 -0
  24. package/es6/src/scripts/user.js +209 -0
  25. package/es6/src/server-manager.js +284 -0
  26. package/es6/src/sql-pretty.transport.js +20 -0
  27. package/es6/src/type-orm.module.js +105 -0
  28. package/es6/src/type-orm.provider.js +26 -0
  29. package/es6/src/type-orm.repository.js +20 -0
  30. package/es6/src/typeorm-scribe.logger.js +60 -0
  31. package/es6/src/typeorm.extensions.js +50 -0
  32. package/es6/src/unit-of-work.js +39 -0
  33. package/package.json +30 -0
  34. package/types/src/bootstrap-policy.d.ts +19 -0
  35. package/types/src/bootstrap.d.ts +16 -0
  36. package/types/src/data-source.factory.d.ts +17 -0
  37. package/types/src/database-options.d.ts +9 -0
  38. package/types/src/dialect-map.d.ts +8 -0
  39. package/types/src/index.d.ts +7 -0
  40. package/types/src/inject-data-source.d.ts +14 -0
  41. package/types/src/scripts/user.d.ts +56 -0
  42. package/types/src/server-manager.d.ts +39 -0
  43. package/types/src/sql-pretty.transport.d.ts +2 -0
  44. package/types/src/type-orm.module.d.ts +17 -0
  45. package/types/src/type-orm.provider.d.ts +14 -0
  46. package/types/src/type-orm.repository.d.ts +12 -0
  47. package/types/src/typeorm-scribe.logger.d.ts +9 -0
  48. package/types/src/typeorm.extensions.d.ts +11 -0
  49. package/types/src/unit-of-work.d.ts +20 -0
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "PostgresServerManager", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return PostgresServerManager;
9
+ }
10
+ });
11
+ const _data = require("@decohere/data");
12
+ const _pg = require("pg");
13
+ const _user = require("./scripts/user.js");
14
+ function _ts_add_disposable_resource(env, value, async) {
15
+ if (value !== null && value !== void 0) {
16
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
17
+ var dispose, inner;
18
+ if (async) {
19
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
20
+ dispose = value[Symbol.asyncDispose];
21
+ }
22
+ if (dispose === void 0) {
23
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
24
+ dispose = value[Symbol.dispose];
25
+ if (async) inner = dispose;
26
+ }
27
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
28
+ if (inner) dispose = function() {
29
+ try {
30
+ inner.call(this);
31
+ } catch (e) {
32
+ return Promise.reject(e);
33
+ }
34
+ };
35
+ env.stack.push({
36
+ value: value,
37
+ dispose: dispose,
38
+ async: async
39
+ });
40
+ } else if (async) {
41
+ env.stack.push({
42
+ async: true
43
+ });
44
+ }
45
+ return value;
46
+ }
47
+ function _ts_dispose_resources(env) {
48
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
49
+ var e = new Error(message);
50
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
51
+ };
52
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
53
+ function fail(e) {
54
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
55
+ env.hasError = true;
56
+ }
57
+ var r, s = 0;
58
+ function next() {
59
+ while(r = env.stack.pop()){
60
+ try {
61
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
62
+ if (r.dispose) {
63
+ var result = r.dispose.call(r.value);
64
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
65
+ fail(e);
66
+ return next();
67
+ });
68
+ } else s |= 1;
69
+ } catch (e) {
70
+ fail(e);
71
+ }
72
+ }
73
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
74
+ if (env.hasError) throw env.error;
75
+ }
76
+ return next();
77
+ })(env);
78
+ }
79
+ /**
80
+ * Official Postgres images always have this DB. `pg` defaults an omitted
81
+ * `database` to the username — bootstrap roles like `decohere_bootstrap` are
82
+ * not databases, so connect here before CREATE DATABASE.
83
+ */ const MAINTENANCE_DATABASE = "postgres";
84
+ class PostgresServerManager {
85
+ applicationName;
86
+ config;
87
+ pool;
88
+ client;
89
+ constructor(applicationName, config){
90
+ this.applicationName = applicationName;
91
+ this.config = config;
92
+ }
93
+ /** `auth: trust`: the server lets every connection in, so roles have no password. */ get trusted() {
94
+ return this.config.auth === "trust";
95
+ }
96
+ async connect() {
97
+ const { adminUser, adminPassword, host, port } = this.config;
98
+ if (!adminUser || !adminPassword && !this.trusted) {
99
+ throw new _data.DataConfigurationError(`Data source "${this.config.name}": adminUser and adminPassword are required to bootstrap the database (adminPassword may be left out only with auth: trust)`);
100
+ }
101
+ this.pool = new _pg.Pool({
102
+ user: adminUser,
103
+ host,
104
+ password: adminPassword,
105
+ port,
106
+ database: MAINTENANCE_DATABASE,
107
+ application_name: this.applicationName
108
+ });
109
+ try {
110
+ this.client = await this.pool.connect();
111
+ } catch (err) {
112
+ const cause = err instanceof Error ? err.message : String(err);
113
+ throw new _data.DataConfigurationError(`Cannot connect to PostgreSQL at ${host}:${port}. Is the server running? Cause: ${cause}`);
114
+ }
115
+ }
116
+ async initializeDatabase(database) {
117
+ (0, _user.quoteIdent)(database, "database");
118
+ const result = await this.pool.query(`SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower($1)`, [
119
+ database
120
+ ]);
121
+ if (result.rowCount === 1) {
122
+ return;
123
+ }
124
+ const dbIdent = (0, _user.quoteIdent)(database, "database");
125
+ await this.pool.query(`CREATE DATABASE ${dbIdent}`);
126
+ }
127
+ /**
128
+ * Create the runtime app role (+ optional migrate role) and its schema, with least-privilege
129
+ * grants. Running it again changes nothing: each grant is made only where the role lacks it,
130
+ * since Postgres checks the grantor's rights even for a grant that would change nothing.
131
+ *
132
+ * The admin acts with the database owner's rights while it runs (it is made a member of the
133
+ * owner, and of the migrate role, only for as long as it needs to be). That is how it creates a
134
+ * schema and grants on it once the migrate role owns the database.
135
+ */ async provisionRoles(options) {
136
+ const { database, appUsername, appPassword, migrateUsername, migratePassword, allowAppDdl, schema = "public" } = options;
137
+ (0, _user.quoteIdent)(schema, "schema");
138
+ if (appUsername === this.config.adminUser) {
139
+ throw new _data.DataConfigurationError(`Runtime username "${appUsername}" must not equal adminUser — use a dedicated app role`);
140
+ }
141
+ if (migrateUsername && migrateUsername === appUsername) {
142
+ throw new _data.DataConfigurationError("migrateUsername must differ from the runtime app username");
143
+ }
144
+ if (migrateUsername && migrateUsername === this.config.adminUser) {
145
+ throw new _data.DataConfigurationError("migrateUsername must not equal adminUser");
146
+ }
147
+ const adminUser = this.config.adminUser;
148
+ if (!adminUser) {
149
+ throw new _data.DataConfigurationError("adminUser is required to provision database roles");
150
+ }
151
+ const pool = new _pg.Pool({
152
+ host: this.config.host,
153
+ port: this.config.port,
154
+ user: adminUser,
155
+ database,
156
+ password: this.config.adminPassword,
157
+ application_name: this.applicationName
158
+ });
159
+ try {
160
+ const env = {
161
+ stack: [],
162
+ error: void 0,
163
+ hasError: false
164
+ };
165
+ try {
166
+ const roles = _ts_add_disposable_resource(env, new BorrowedRoles(pool, adminUser), true);
167
+ if (migrateUsername) {
168
+ await this.ensureRole(pool, migrateUsername, migratePassword);
169
+ // Membership is required for OWNER TO and DEFAULT PRIVILEGES FOR ROLE (not superuser).
170
+ await roles.borrow(migrateUsername);
171
+ // The owner holds every privilege on the database, so no separate GRANT is needed.
172
+ if (await databaseOwner(pool, database) !== migrateUsername) {
173
+ await pool.query((0, _user.alterDatabaseOwnerQuery)(database, migrateUsername).text);
174
+ }
175
+ }
176
+ const owner = await databaseOwner(pool, database);
177
+ if (owner !== adminUser) await roles.borrow(owner);
178
+ // Owned by the database owner (the migrate role, when there is one), like `public`.
179
+ await pool.query((0, _user.createSchemaQuery)(schema, owner).text);
180
+ if (migrateUsername && !await hasAll(pool, (privilege)=>(0, _user.hasSchemaPrivilegeQuery)(migrateUsername, schema, privilege))) {
181
+ await pool.query((0, _user.grantSchemaPrivilegesQuery)(migrateUsername, schema).text);
182
+ }
183
+ await this.ensureRole(pool, appUsername, appPassword);
184
+ if (!await granted(pool, (0, _user.hasDatabasePrivilegeQuery)(appUsername, database, "CONNECT"))) {
185
+ await pool.query((0, _user.grantConnectQuery)(appUsername, database).text);
186
+ }
187
+ if (!await granted(pool, (0, _user.hasSchemaPrivilegeQuery)(appUsername, schema, "USAGE"))) {
188
+ await pool.query((0, _user.grantSchemaUsageQuery)(appUsername, schema).text);
189
+ }
190
+ // Dev synchronize: the app connection must be able to CREATE tables.
191
+ if (allowAppDdl && !await granted(pool, (0, _user.hasSchemaPrivilegeQuery)(appUsername, schema, "CREATE"))) {
192
+ await pool.query((0, _user.grantSchemaCreateQuery)(appUsername, schema).text);
193
+ }
194
+ if (migrateUsername) {
195
+ // Setting a default privilege that is already set changes nothing.
196
+ for (const q of (0, _user.defaultPrivilegesForAppQueries)(migrateUsername, appUsername, schema)){
197
+ await pool.query(q.text);
198
+ }
199
+ }
200
+ } catch (e) {
201
+ env.error = e;
202
+ env.hasError = true;
203
+ } finally{
204
+ const result = _ts_dispose_resources(env);
205
+ if (result) await result;
206
+ }
207
+ } finally{
208
+ await pool.end();
209
+ }
210
+ }
211
+ /** @deprecated Use provisionRoles. */ async createApiUser(username, password, database, _role) {
212
+ await this.provisionRoles({
213
+ database,
214
+ appUsername: username,
215
+ appPassword: password,
216
+ migrateUsername: this.config.migrateUsername,
217
+ migratePassword: this.config.migratePassword,
218
+ allowAppDdl: this.config.synchronize === true,
219
+ schema: this.config.schema
220
+ });
221
+ }
222
+ async ensureRole(pool, username, password) {
223
+ if (!password && !this.trusted) {
224
+ throw new _data.DataConfigurationError(`A password is required for database role "${username}" unless the data source sets auth: trust`);
225
+ }
226
+ const exists = (0, _user.roleExistsQuery)(username);
227
+ const found = await pool.query(exists.text, exists.values);
228
+ if (found.rowCount === 1) {
229
+ return;
230
+ }
231
+ const create = (0, _user.createUserQuery)(username, password);
232
+ await pool.query(create.text, create.values);
233
+ }
234
+ [Symbol.asyncDispose]() {
235
+ return this.closeConnection();
236
+ }
237
+ async closeConnection() {
238
+ this.client?.release();
239
+ await this.pool?.end();
240
+ }
241
+ }
242
+ async function granted(pool, query) {
243
+ const result = await pool.query(query.text, query.values);
244
+ return result.rows[0]?.granted === true;
245
+ }
246
+ /** Every schema privilege that `GRANT ALL ON SCHEMA` gives. Checked one at a time: Postgres
247
+ * answers true for a list when any one of them is held. */ async function hasAll(pool, query) {
248
+ for (const privilege of [
249
+ "USAGE",
250
+ "CREATE"
251
+ ]){
252
+ if (!await granted(pool, query(privilege))) return false;
253
+ }
254
+ return true;
255
+ }
256
+ async function databaseOwner(pool, database) {
257
+ const query = (0, _user.databaseOwnerQuery)(database);
258
+ const result = await pool.query(query.text, query.values);
259
+ const owner = result.rows[0]?.owner;
260
+ if (owner == null) {
261
+ throw new _data.DataConfigurationError(`Database "${database}" does not exist`);
262
+ }
263
+ return owner;
264
+ }
265
+ /**
266
+ * Roles the admin is made a member of for one provisioning run, so it acts with their rights.
267
+ * Disposing gives back exactly what was borrowed, even when the run fails: memberships the admin
268
+ * already had (or rights it has as a superuser) are left alone.
269
+ */ class BorrowedRoles {
270
+ pool;
271
+ adminUser;
272
+ borrowed = [];
273
+ constructor(pool, adminUser){
274
+ this.pool = pool;
275
+ this.adminUser = adminUser;
276
+ }
277
+ async borrow(role) {
278
+ if (this.borrowed.includes(role)) return;
279
+ if (await granted(this.pool, (0, _user.hasRolePrivilegesQuery)(this.adminUser, role))) return;
280
+ try {
281
+ await this.pool.query((0, _user.grantRoleMembershipQuery)(this.adminUser, role).text);
282
+ } catch (err) {
283
+ throw new _data.DataConfigurationError(`Bootstrap role "${this.adminUser}" cannot act as "${role}". Make it a member of "${role}" (or create "${role}" with it), then run again.`, {
284
+ cause: err
285
+ });
286
+ }
287
+ this.borrowed.push(role);
288
+ }
289
+ async [Symbol.asyncDispose]() {
290
+ for (const role of this.borrowed.reverse()){
291
+ await this.pool.query((0, _user.revokeRoleMembershipQuery)(this.adminUser, role).text);
292
+ }
293
+ }
294
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "SqlPretty", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return SqlPretty;
9
+ }
10
+ });
11
+ const _pinopretty = /*#__PURE__*/ _interop_require_default(require("pino-pretty"));
12
+ const _PlatformTools = require("typeorm/platform/PlatformTools.js");
13
+ function _interop_require_default(obj) {
14
+ return obj && obj.__esModule ? obj : {
15
+ default: obj
16
+ };
17
+ }
18
+ const SqlPretty = (opts)=>(0, _pinopretty.default)({
19
+ colorizeObjects: true,
20
+ customLevels: Object.entries(opts?.levels ?? []).map(([key, value])=>`${key}:${value}`).join(",") ?? [],
21
+ customPrettifiers: {
22
+ sql: tryParseSql
23
+ },
24
+ ...opts
25
+ });
26
+ function tryParseSql(value) {
27
+ const isString = typeof value === "string";
28
+ const statement = isString ? value : value.statement;
29
+ try {
30
+ const formatted = _PlatformTools.PlatformTools.highlightSql(_PlatformTools.PlatformTools.formatSql(statement));
31
+ return formatted;
32
+ } catch {
33
+ return statement;
34
+ }
35
+ }
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TypeOrmModule", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TypeOrmModule;
9
+ }
10
+ });
11
+ const _data = require("@decohere/data");
12
+ const _http = require("@decohere/http");
13
+ const _caching = require("@decohere/core/caching");
14
+ const _bootstrap = require("./bootstrap.js");
15
+ const _datasourcefactory = require("./data-source.factory.js");
16
+ const _injectdatasource = require("./inject-data-source.js");
17
+ const _typeormscribelogger = require("./typeorm-scribe.logger.js");
18
+ const _unitofwork = require("./unit-of-work.js");
19
+ function _ts_decorate(decorators, target, key, desc) {
20
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
21
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
22
+ 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;
23
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
24
+ }
25
+ function _ts_metadata(k, v) {
26
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
27
+ }
28
+ class TypeOrmModule {
29
+ /** Registers and opens a DataSource per module. Returns the names it registered them under. */ async configure(options) {
30
+ const { moduleConfigurations, databaseConfig, containerBuilder, applicationName } = options;
31
+ if (databaseConfig.dataSources.length === 0) {
32
+ throw new _data.DataConfigurationError("No datasources detected in config");
33
+ }
34
+ const modules = this.resolveDataSources(databaseConfig, moduleConfigurations);
35
+ // Once, before any DataSource opens: modules sharing a database must not race to create it.
36
+ await (0, _bootstrap.bootstrapDataSources)(modules.map((m)=>m.connectionInfo), {
37
+ applicationName
38
+ });
39
+ return await Promise.all(modules.map(async ({ name, connectionInfo, moduleConfig })=>{
40
+ await this.init(applicationName, name, connectionInfo, moduleConfig, containerBuilder);
41
+ return name;
42
+ }));
43
+ }
44
+ resolveDataSources(databaseConfig, moduleConfigurations) {
45
+ if (databaseConfig.dataSources.length === 1 && moduleConfigurations.length === 1) {
46
+ const moduleConfig = moduleConfigurations.at(0);
47
+ return [
48
+ {
49
+ name: moduleConfig.name ?? _data.DEFAULT_DATA_SOURCE,
50
+ connectionInfo: databaseConfig.dataSources.at(0),
51
+ moduleConfig
52
+ }
53
+ ];
54
+ }
55
+ return moduleConfigurations.map((moduleConfig)=>{
56
+ const { name } = moduleConfig;
57
+ if (name == null) {
58
+ throw new _data.DataConfigurationError(`Name is required if there is more than one datasource`);
59
+ }
60
+ const connectionInfo = databaseConfig.dataSources.find((ds)=>ds.name === name);
61
+ if (connectionInfo == null) {
62
+ throw new _data.DataConfigurationError(`Cannot find connection info for ${name.toString()}`);
63
+ }
64
+ return {
65
+ name,
66
+ connectionInfo,
67
+ moduleConfig
68
+ };
69
+ });
70
+ }
71
+ async init(applicationName, name, connectionInfo, moduleConfig, builder) {
72
+ const logger = this.getLoggerFor(name, connectionInfo.dialect);
73
+ const dataSource = await this.configureTypeOrmDataSource(applicationName, name, moduleConfig, connectionInfo, builder, logger);
74
+ if (connectionInfo.seed) {
75
+ await moduleConfig.seed?.(dataSource);
76
+ }
77
+ }
78
+ async configureTypeOrmDataSource(applicationName, name, moduleConfig, connectionInfo, builder, logger) {
79
+ const { entities, repositories } = moduleConfig;
80
+ const dataSource = _datasourcefactory.DataSourceFactory.create({
81
+ entities,
82
+ applicationName,
83
+ ...connectionInfo
84
+ }, logger);
85
+ await dataSource.initialize();
86
+ const unitOfWork = ()=>new _unitofwork.TypeOrmUnitOfWork(dataSource);
87
+ builder.registerRequestScoped(name, unitOfWork);
88
+ builder.registerSingleton((0, _injectdatasource.typeOrmDataSourceToken)(name), dataSource);
89
+ builder.registerSingleton(_http.ReadinessCheckToken, createTypeOrmReadinessCheck(name, dataSource));
90
+ for (const repo of repositories ?? []){
91
+ builder.registerRequestScoped(repo);
92
+ }
93
+ return dataSource;
94
+ }
95
+ getLoggerFor(name, dialectOrProvider) {
96
+ return new _typeormscribelogger.TypeOrmScribeLogger(name.toString(), dialectOrProvider);
97
+ }
98
+ }
99
+ _ts_decorate([
100
+ (0, _caching.memoize)(),
101
+ _ts_metadata("design:type", Function),
102
+ _ts_metadata("design:paramtypes", [
103
+ Object,
104
+ Object
105
+ ]),
106
+ _ts_metadata("design:returntype", void 0)
107
+ ], TypeOrmModule.prototype, "getLoggerFor", null);
108
+ function createTypeOrmReadinessCheck(name, dataSource) {
109
+ return {
110
+ name: `typeorm:${String(name)}`,
111
+ async check () {
112
+ await dataSource.query("SELECT 1");
113
+ }
114
+ };
115
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TypeOrmQueryProvider", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TypeOrmQueryProvider;
9
+ }
10
+ });
11
+ class TypeOrmQueryProvider {
12
+ unitOfWork;
13
+ constructor(unitOfWork){
14
+ this.unitOfWork = unitOfWork;
15
+ }
16
+ firstOrDefault(entity, options) {
17
+ return this.unitOfWork.entityManager.findOne(entity, options);
18
+ }
19
+ all(entity, options) {
20
+ return this.unitOfWork.getRepository(entity).find(options);
21
+ }
22
+ findById(entity, key) {
23
+ return this.unitOfWork.entityManager.findOneBy(entity, {
24
+ id: key
25
+ });
26
+ }
27
+ save(entity) {
28
+ return this.unitOfWork.entityManager.save(entity);
29
+ }
30
+ query(entity, filter) {
31
+ return this.unitOfWork.entityManager.find(entity, filter);
32
+ }
33
+ delete(entity) {
34
+ return this.unitOfWork.entityManager.remove(entity);
35
+ }
36
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TypeOrmRepository", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TypeOrmRepository;
9
+ }
10
+ });
11
+ const _data = require("@decohere/data");
12
+ const _typeormprovider = require("./type-orm.provider.js");
13
+ class TypeOrmRepository extends _data.Repository {
14
+ provider;
15
+ type;
16
+ constructor(unitOfWork, type){
17
+ super();
18
+ this.type = type;
19
+ this.provider = new _typeormprovider.TypeOrmQueryProvider(unitOfWork);
20
+ }
21
+ firstOrDefault(optionsOrType, options) {
22
+ if (typeof optionsOrType === "function") {
23
+ if (!options) {
24
+ throw new Error("options parameter is required when type is provided");
25
+ }
26
+ return this.provider.firstOrDefault(optionsOrType, options);
27
+ }
28
+ return this.provider.firstOrDefault(this.type, optionsOrType);
29
+ }
30
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "TypeOrmScribeLogger", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return TypeOrmScribeLogger;
9
+ }
10
+ });
11
+ const _caching = require("@decohere/core/caching");
12
+ const _scribe = require("@decohere/scribe");
13
+ const _typeorm = require("typeorm");
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ const MessageTypeMap = {
24
+ log: "info",
25
+ info: "info",
26
+ query: "info",
27
+ warn: "warn",
28
+ error: "error",
29
+ "query-error": "error",
30
+ "query-slow": "warn",
31
+ "schema-build": "info",
32
+ migration: "info"
33
+ };
34
+ class TypeOrmScribeLogger extends _typeorm.AbstractLogger {
35
+ logger;
36
+ dialect;
37
+ constructor(name, dialect, enable = true){
38
+ super(enable);
39
+ this.dialect = dialect;
40
+ this.logger = _scribe.scribe.logger(`${name ?? "TypeOrm"}`);
41
+ }
42
+ writeLog(level, logMessage, _queryRunner) {
43
+ const messages = Array.isArray(logMessage) ? logMessage : [
44
+ logMessage
45
+ ];
46
+ for (const message of messages){
47
+ const logLevel = this.getLogLevel(message.type);
48
+ const prefix = message.type ?? level;
49
+ const statement = {
50
+ sql: {
51
+ statement: message.message,
52
+ language: this.dialect
53
+ }
54
+ };
55
+ this.logger[logLevel](prefix, statement);
56
+ }
57
+ }
58
+ getLogLevel(type) {
59
+ const level = Object.entries(MessageTypeMap).find(([key])=>type === key)?.at(1);
60
+ return this.logger.isLevelEnabled(level) ? level : this.logger.currentLevel;
61
+ }
62
+ }
63
+ _ts_decorate([
64
+ (0, _caching.cache)(),
65
+ _ts_metadata("design:type", Function),
66
+ _ts_metadata("design:paramtypes", [
67
+ Object
68
+ ]),
69
+ _ts_metadata("design:returntype", void 0)
70
+ ], TypeOrmScribeLogger.prototype, "getLogLevel", null);
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "BuilderExtensions", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return BuilderExtensions;
9
+ }
10
+ });
11
+ const _data = require("@decohere/data");
12
+ const _http = require("@decohere/http");
13
+ const _extensibility = require("@decohere/core/extensibility");
14
+ const _injectdatasource = require("./inject-data-source.js");
15
+ const _typeormmodule = require("./type-orm.module.js");
16
+ function _ts_decorate(decorators, target, key, desc) {
17
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
+ 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;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ }
22
+ function _ts_metadata(k, v) {
23
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
24
+ }
25
+ class BuilderExtensions {
26
+ static withTypeOrm(builder, config) {
27
+ const names = [];
28
+ builder.registerPreBuildStep(async (configService, containerBuilder)=>{
29
+ const databaseConfig = await configService.get(_data.DatabaseConfig);
30
+ const module = new _typeormmodule.TypeOrmModule();
31
+ const moduleConfigurations = Array.isArray(config) ? config : [
32
+ config
33
+ ];
34
+ const applicationName = builder.applicationName;
35
+ names.push(...await module.configure({
36
+ applicationName,
37
+ databaseConfig,
38
+ moduleConfigurations,
39
+ containerBuilder
40
+ }));
41
+ });
42
+ // The container disposes only what it has handed out, and nothing may ever ask for a
43
+ // DataSource by its token. Resolving each here makes the root container own it, as one of
44
+ // its first instances, so it is closed last: after hosted services and other services
45
+ // that use it (#541).
46
+ builder.registerPostBuildStep((container)=>{
47
+ for (const name of names)container.resolve((0, _injectdatasource.typeOrmDataSourceToken)(name));
48
+ });
49
+ return builder;
50
+ }
51
+ }
52
+ _ts_decorate([
53
+ (0, _extensibility.extension)(_http.Builder),
54
+ _ts_metadata("design:type", Function),
55
+ _ts_metadata("design:paramtypes", [
56
+ typeof _http.Builder === "undefined" ? Object : _http.Builder,
57
+ Object
58
+ ]),
59
+ _ts_metadata("design:returntype", void 0)
60
+ ], BuilderExtensions, "withTypeOrm", null);