@sentzunhat/zacatl 0.0.20 β 0.0.22
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 +20 -2
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/orm-exports.d.ts +5 -0
- package/build/orm-exports.d.ts.map +1 -0
- package/build/orm-exports.js +3 -0
- package/build/orm-exports.js.map +1 -0
- package/build/service/architecture/infrastructure/orm/adapter-loader.d.ts +5 -0
- package/build/service/architecture/infrastructure/orm/adapter-loader.d.ts.map +1 -0
- package/build/service/architecture/infrastructure/orm/adapter-loader.js +27 -0
- package/build/service/architecture/infrastructure/orm/adapter-loader.js.map +1 -0
- package/build/service/architecture/infrastructure/orm/adapters/mongoose-adapter.d.ts +1 -1
- package/build/service/architecture/infrastructure/orm/adapters/mongoose-adapter.d.ts.map +1 -1
- package/build/service/architecture/infrastructure/orm/adapters/mongoose-adapter.js +2 -4
- package/build/service/architecture/infrastructure/orm/adapters/mongoose-adapter.js.map +1 -1
- package/build/service/architecture/infrastructure/repositories/abstract.d.ts +8 -3
- package/build/service/architecture/infrastructure/repositories/abstract.d.ts.map +1 -1
- package/build/service/architecture/infrastructure/repositories/abstract.js +39 -9
- package/build/service/architecture/infrastructure/repositories/abstract.js.map +1 -1
- package/build/test/tsconfig.tsbuildinfo +1 -1
- package/package.json +53 -8
- package/src/index.ts +3 -0
- package/src/orm-exports.ts +23 -0
- package/src/service/architecture/infrastructure/orm/adapter-loader.ts +54 -0
- package/src/service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts +10 -11
- package/src/service/architecture/infrastructure/repositories/abstract.ts +76 -22
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
[](https://nodejs.org/)
|
|
8
|
-
[](#testing)
|
|
9
9
|
[](#testing)
|
|
10
10
|
|
|
11
11
|
**Production-ready TypeScript framework for building scalable microservices, APIs, and distributed systems.**
|
|
@@ -21,7 +21,7 @@ Zacatl enforces clean, layered architecture with dependency injection, validatio
|
|
|
21
21
|
- **ποΈ Pluggable ORM Adapters** - Sequelize, Mongoose, or build your own
|
|
22
22
|
- **π Multi-Language Support** - Pluggable i18n with filesystem/memory adapters
|
|
23
23
|
- **π Adapter Pattern** - Easy integration with any database or service
|
|
24
|
-
- **π§ͺ Comprehensive Testing** -
|
|
24
|
+
- **π§ͺ Comprehensive Testing** - 169 tests, 79% coverage, Vitest
|
|
25
25
|
- **β‘ Runtime Detection** - Works with Node.js 22+ and Bun
|
|
26
26
|
- **π Production Ready** - Structured logging, monitoring, and error tracking
|
|
27
27
|
|
|
@@ -47,6 +47,20 @@ Zacatl is MIT-licensed (permissive). Please donβt use it to harm people.
|
|
|
47
47
|
npm install @sentzunhat/zacatl
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
## π¦ Import Shortcuts (v0.0.22+)
|
|
51
|
+
|
|
52
|
+
> **New in v0.0.22:** ESM runtime compatibility fix. Adapters now use dynamic `import()` instead of `require()`. [Migration Guide](./docs/migration/v0.0.22.md)
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// Short imports for better DX
|
|
56
|
+
import { BaseRepository, ORMType } from "@sentzunhat/zacatl/infrastructure";
|
|
57
|
+
import { CustomError } from "@sentzunhat/zacatl/errors";
|
|
58
|
+
import { loadConfig } from "@sentzunhat/zacatl/config";
|
|
59
|
+
|
|
60
|
+
// Or full path (still works)
|
|
61
|
+
import { BaseRepository } from "@sentzunhat/zacatl/build/service/architecture/infrastructure/repositories/abstract";
|
|
62
|
+
```
|
|
63
|
+
|
|
50
64
|
### Hello World HTTP Service
|
|
51
65
|
|
|
52
66
|
```typescript
|
|
@@ -362,3 +376,7 @@ Zacatl is built for developers who value clean architecture, type safety, and te
|
|
|
362
376
|
**Created by**: [Diego Beltran](https://www.linkedin.com/in/diego-beltran)
|
|
363
377
|
**Repository**: https://github.com/sentzunhat/zacatl
|
|
364
378
|
**npm**: https://www.npmjs.com/package/@sentzunhat/zacatl
|
|
379
|
+
|
|
380
|
+
## π€ Acknowledgments
|
|
381
|
+
|
|
382
|
+
This framework was built with assistance from **GitHub Copilot** and friendly ML/LLM models, demonstrating effective human-AI collaboration in software development.
|
package/build/index.d.ts
CHANGED
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"./src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,uCAAuC,CAAC;AAGtD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,+CAA+C,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAGlF,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"./src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,uCAAuC,CAAC;AAGtD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,+CAA+C,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAGlF,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGxD,cAAc,eAAe,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -12,4 +12,5 @@ export * from "./service/architecture/infrastructure";
|
|
|
12
12
|
export { ServerType, ServerVendor, DatabaseVendor, HandlersType, } from "./service/architecture/platform/server/server";
|
|
13
13
|
export { container } from "tsyringe";
|
|
14
14
|
export { z } from "zod";
|
|
15
|
+
export * from "./orm-exports";
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"./src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,uCAAuC,CAAC;AAGtD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,+CAA+C,CAAC;AAIvD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAIrC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC","sourcesContent":["export * from \"./optionals\";\nexport * from \"./configuration\";\nexport * from \"./utils\";\nexport * from \"./error\";\nexport * from \"./dependency-injection\";\nexport * from \"./service\";\nexport { Service } from \"./service\";\nexport type { ConfigService } from \"./service\";\nexport * from \"./logs\";\nexport * from \"./runtime\";\nexport * from \"./localization\";\n\n// Re-export infrastructure with ORM types\nexport * from \"./service/architecture/infrastructure\";\n\n// Re-export server types for convenience\nexport {\n ServerType,\n ServerVendor,\n DatabaseVendor,\n HandlersType,\n} from \"./service/architecture/platform/server/server\";\nexport type { ConfigServer } from \"./service/architecture/platform/server/server\";\n\n// Re-export commonly used third-party packages\nexport { container } from \"tsyringe\";\nexport type { DependencyContainer } from \"tsyringe\";\n\n// Re-export Zod for validation\nexport { z } from \"zod\";\nexport type { ZodSchema, ZodType, ZodError } from \"zod\";\n\n// Note: TypeScript utility types (Partial, Required, Readonly, etc.)\n// are globally available and don't need re-export\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"./src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,uCAAuC,CAAC;AAGtD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,GACb,MAAM,+CAA+C,CAAC;AAIvD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAIrC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,cAAc,eAAe,CAAC","sourcesContent":["export * from \"./optionals\";\nexport * from \"./configuration\";\nexport * from \"./utils\";\nexport * from \"./error\";\nexport * from \"./dependency-injection\";\nexport * from \"./service\";\nexport { Service } from \"./service\";\nexport type { ConfigService } from \"./service\";\nexport * from \"./logs\";\nexport * from \"./runtime\";\nexport * from \"./localization\";\n\n// Re-export infrastructure with ORM types\nexport * from \"./service/architecture/infrastructure\";\n\n// Re-export server types for convenience\nexport {\n ServerType,\n ServerVendor,\n DatabaseVendor,\n HandlersType,\n} from \"./service/architecture/platform/server/server\";\nexport type { ConfigServer } from \"./service/architecture/platform/server/server\";\n\n// Re-export commonly used third-party packages\nexport { container } from \"tsyringe\";\nexport type { DependencyContainer } from \"tsyringe\";\n\n// Re-export Zod for validation\nexport { z } from \"zod\";\nexport type { ZodSchema, ZodType, ZodError } from \"zod\";\n\n// Re-export ORMs (included as dependencies)\nexport * from \"./orm-exports\";\n\n// Note: TypeScript utility types (Partial, Required, Readonly, etc.)\n// are globally available and don't need re-export\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as mongoose, Mongoose, Schema, Model, Document, connect, connection, } from "mongoose";
|
|
2
|
+
export { Sequelize, Model as SequelizeModel, DataTypes, Op } from "sequelize";
|
|
3
|
+
export type { Model as MongooseModel } from "mongoose";
|
|
4
|
+
export type { ModelStatic, Options as SequelizeOptions } from "sequelize";
|
|
5
|
+
//# sourceMappingURL=orm-exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orm-exports.d.ts","sourceRoot":"./src/","sources":["orm-exports.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,OAAO,IAAI,QAAQ,EACnB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,OAAO,EACP,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,SAAS,EAAE,KAAK,IAAI,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAG9E,YAAY,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orm-exports.js","sourceRoot":"./src/","sources":["orm-exports.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,OAAO,IAAI,QAAQ,EACnB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,OAAO,EACP,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,SAAS,EAAE,KAAK,IAAI,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC","sourcesContent":["/**\n * Re-export ORM dependencies for convenience\n * These are included as dependencies (currently) for backward compatibility\n * Future versions may move them to pure peer dependencies\n */\n\n// Mongoose exports - full re-export\nexport {\n default as mongoose,\n Mongoose,\n Schema,\n Model,\n Document,\n connect,\n connection,\n} from \"mongoose\";\n\n// Sequelize exports - full re-export\nexport { Sequelize, Model as SequelizeModel, DataTypes, Op } from \"sequelize\";\n\n// Type-only exports for convenience\nexport type { Model as MongooseModel } from \"mongoose\";\nexport type { ModelStatic, Options as SequelizeOptions } from \"sequelize\";\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Model } from "sequelize";
|
|
2
|
+
import type { MongooseRepositoryConfig, SequelizeRepositoryConfig, ORMAdapter } from "../repositories/types";
|
|
3
|
+
export declare function loadMongooseAdapter<D, I, O>(config: MongooseRepositoryConfig<D>): Promise<ORMAdapter<D, I, O>>;
|
|
4
|
+
export declare function loadSequelizeAdapter<D extends Model, I, O>(config: SequelizeRepositoryConfig<D>): Promise<ORMAdapter<D, I, O>>;
|
|
5
|
+
//# sourceMappingURL=adapter-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-loader.d.ts","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapter-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EACzB,UAAU,EACX,MAAM,uBAAuB,CAAC;AAM/B,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/C,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAClC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAgB9B;AAMD,wBAAsB,oBAAoB,CAAC,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,CAAC,EAC9D,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACnC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAgB9B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export async function loadMongooseAdapter(config) {
|
|
2
|
+
try {
|
|
3
|
+
const adapters = await import("./adapters/mongoose-adapter");
|
|
4
|
+
return new adapters.MongooseAdapter(config);
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" ||
|
|
8
|
+
error.code === "MODULE_NOT_FOUND") {
|
|
9
|
+
throw new Error("Mongoose is not installed. Install it with: npm install mongoose");
|
|
10
|
+
}
|
|
11
|
+
throw error;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function loadSequelizeAdapter(config) {
|
|
15
|
+
try {
|
|
16
|
+
const adapters = await import("./adapters/sequelize-adapter");
|
|
17
|
+
return new adapters.SequelizeAdapter(config);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" ||
|
|
21
|
+
error.code === "MODULE_NOT_FOUND") {
|
|
22
|
+
throw new Error("Sequelize is not installed. Install it with: npm install sequelize");
|
|
23
|
+
}
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=adapter-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-loader.js","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapter-loader.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAmC;IAEnC,IAAI,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAC7D,OAAO,IAAI,QAAQ,CAAC,eAAe,CAAU,MAAM,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IACE,KAAK,CAAC,IAAI,KAAK,sBAAsB;YACrC,KAAK,CAAC,IAAI,KAAK,kBAAkB,EACjC,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAoC;IAEpC,IAAI,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAC9D,OAAO,IAAI,QAAQ,CAAC,gBAAgB,CAAU,MAAM,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IACE,KAAK,CAAC,IAAI,KAAK,sBAAsB;YACrC,KAAK,CAAC,IAAI,KAAK,kBAAkB,EACjC,CAAC;YACD,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { Model } from \"sequelize\";\nimport type {\n MongooseRepositoryConfig,\n SequelizeRepositoryConfig,\n ORMAdapter,\n} from \"../repositories/types\";\n\n/**\n * Loads MongooseAdapter dynamically - only when needed\n * Throws helpful error if mongoose is not installed\n */\nexport async function loadMongooseAdapter<D, I, O>(\n config: MongooseRepositoryConfig<D>,\n): Promise<ORMAdapter<D, I, O>> {\n try {\n // Dynamic import - only loads when Mongoose is actually used\n const adapters = await import(\"./adapters/mongoose-adapter\");\n return new adapters.MongooseAdapter<D, I, O>(config);\n } catch (error: any) {\n if (\n error.code === \"ERR_MODULE_NOT_FOUND\" ||\n error.code === \"MODULE_NOT_FOUND\"\n ) {\n throw new Error(\n \"Mongoose is not installed. Install it with: npm install mongoose\",\n );\n }\n throw error;\n }\n}\n\n/**\n * Loads SequelizeAdapter dynamically - only when needed\n * Throws helpful error if sequelize is not installed\n */\nexport async function loadSequelizeAdapter<D extends Model, I, O>(\n config: SequelizeRepositoryConfig<D>,\n): Promise<ORMAdapter<D, I, O>> {\n try {\n // Dynamic import - only loads when Sequelize is actually used\n const adapters = await import(\"./adapters/sequelize-adapter\");\n return new adapters.SequelizeAdapter<D, I, O>(config);\n } catch (error: any) {\n if (\n error.code === \"ERR_MODULE_NOT_FOUND\" ||\n error.code === \"MODULE_NOT_FOUND\"\n ) {\n throw new Error(\n \"Sequelize is not installed. Install it with: npm install sequelize\",\n );\n }\n throw error;\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Model as MongooseModel } from "mongoose";
|
|
1
|
+
import type { Model as MongooseModel } from "mongoose";
|
|
2
2
|
import type { MongooseRepositoryConfig, ORMAdapter } from "../../repositories/types";
|
|
3
3
|
export declare class MongooseAdapter<D, I, O> implements ORMAdapter<D, I, O> {
|
|
4
4
|
readonly model: MongooseModel<D>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongoose-adapter.d.ts","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"mongoose-adapter.d.ts","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AAIvD,OAAO,KAAK,EACV,wBAAwB,EACxB,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAWlC,qBAAa,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAClE,SAAgB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;gBAEzC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAmBxC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,IAAI;IAoDjC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IASvC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY7B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IASzD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CAQ5C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Mongoose } from "mongoose";
|
|
2
2
|
import { v4 as uuidv4 } from "uuid";
|
|
3
3
|
import { container } from "tsyringe";
|
|
4
4
|
export class MongooseAdapter {
|
|
@@ -6,9 +6,7 @@ export class MongooseAdapter {
|
|
|
6
6
|
config;
|
|
7
7
|
constructor(config) {
|
|
8
8
|
this.config = config;
|
|
9
|
-
const mongoose =
|
|
10
|
-
? importedMongoose
|
|
11
|
-
: container.resolve(Mongoose);
|
|
9
|
+
const mongoose = container.resolve(Mongoose);
|
|
12
10
|
const { name, schema } = this.config;
|
|
13
11
|
if (name) {
|
|
14
12
|
this.model = mongoose.model(name, schema);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongoose-adapter.js","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mongoose-adapter.js","sourceRoot":"./src/","sources":["service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model as MongooseModel } from \"mongoose\";\nimport { Mongoose } from \"mongoose\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { container } from \"tsyringe\";\nimport type {\n MongooseRepositoryConfig,\n ORMAdapter,\n LeanWithMeta,\n} from \"../../repositories/types\";\n\n/**\n * MongooseAdapter - Handles Mongoose-specific ORM operations\n *\n * Provides consistent interface for repository layer with:\n * - Document transformation\n * - ID normalization\n * - Timestamp management\n * - Connection instance from DI container\n */\nexport class MongooseAdapter<D, I, O> implements ORMAdapter<D, I, O> {\n public readonly model: MongooseModel<D>;\n private readonly config: MongooseRepositoryConfig<D>;\n\n constructor(config: MongooseRepositoryConfig<D>) {\n this.config = config;\n // Get mongoose instance from DI container - allows per-database configuration\n // Connection strings should be set up before repository instantiation\n const mongoose = container.resolve<Mongoose>(Mongoose);\n\n const { name, schema } = this.config;\n\n if (name) {\n this.model = mongoose.model<D>(name, schema);\n } else {\n this.model = mongoose.model<D>(uuidv4(), schema);\n }\n\n this.model.createCollection();\n this.model.createIndexes();\n this.model.init();\n }\n\n public toLean(input: unknown): O | null {\n if (!input) {\n return null;\n }\n\n let base: LeanWithMeta<O>;\n\n if (\n input &&\n typeof input === \"object\" &&\n \"toObject\" in input &&\n typeof (input as unknown as Record<string, unknown>)[\"toObject\"] ===\n \"function\"\n ) {\n base = (\n input as unknown as {\n toObject: (opt: any) => LeanWithMeta<O>;\n }\n ).toObject({\n virtuals: true,\n }) as LeanWithMeta<O>;\n } else {\n base = input as LeanWithMeta<O>;\n }\n\n const result: O = {\n ...(base as O),\n id:\n typeof base.id === \"string\"\n ? base.id\n : typeof base._id === \"string\"\n ? base._id\n : base._id !== undefined\n ? String(base._id)\n : \"\",\n createdAt:\n base.createdAt instanceof Date\n ? base.createdAt\n : base.createdAt\n ? new Date(base.createdAt as string | number)\n : new Date(),\n updatedAt:\n base.updatedAt instanceof Date\n ? base.updatedAt\n : base.updatedAt\n ? new Date(base.updatedAt as string | number)\n : new Date(),\n } as O;\n\n return result;\n }\n\n async findById(id: string): Promise<O | null> {\n const entity = await this.model\n .findById(id)\n .lean<O>({ virtuals: true })\n .exec();\n\n return this.toLean(entity);\n }\n\n async create(entity: I): Promise<O> {\n const document = await this.model.create(entity as any);\n\n const leanDocument = this.toLean(document);\n\n if (!leanDocument) {\n throw new Error(\"failed to create document\");\n }\n\n return leanDocument;\n }\n\n async update(id: string, update: Partial<I>): Promise<O | null> {\n const entity = await this.model\n .findByIdAndUpdate(id, update as any, { new: true })\n .lean<O>({ virtuals: true })\n .exec();\n\n return this.toLean(entity);\n }\n\n async delete(id: string): Promise<O | null> {\n const entity = await this.model\n .findByIdAndDelete(id)\n .lean<O>({ virtuals: true })\n .exec();\n\n return this.toLean(entity);\n }\n}\n"]}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { Model as MongooseModel } from "mongoose";
|
|
2
|
-
import { ModelStatic } from "sequelize";
|
|
1
|
+
import type { Model as MongooseModel } from "mongoose";
|
|
2
|
+
import type { ModelStatic } from "sequelize";
|
|
3
3
|
import { BaseRepositoryConfig, Repository } from "./types";
|
|
4
4
|
export * from "./types";
|
|
5
5
|
export declare abstract class BaseRepository<D, I, O> implements Repository<D, I, O> {
|
|
6
|
-
private adapter
|
|
6
|
+
private adapter?;
|
|
7
|
+
private readonly ormType;
|
|
8
|
+
private readonly config;
|
|
9
|
+
private initPromise?;
|
|
7
10
|
constructor(config: BaseRepositoryConfig<D>);
|
|
11
|
+
private ensureInitialized;
|
|
12
|
+
private loadAdapter;
|
|
8
13
|
get model(): MongooseModel<D> | ModelStatic<any>;
|
|
9
14
|
isMongoose(): boolean;
|
|
10
15
|
isSequelize(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract.d.ts","sourceRoot":"./src/","sources":["service/architecture/infrastructure/repositories/abstract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"abstract.d.ts","sourceRoot":"./src/","sources":["service/architecture/infrastructure/repositories/abstract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAS,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,UAAU,EAKX,MAAM,SAAS,CAAC;AAMjB,cAAc,SAAS,CAAC;AA8BxB,8BAAsB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAE,YAAW,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,OAAO,CAAC,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,WAAW,CAAC,CAAgB;gBAExB,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;YAS7B,iBAAiB;YAajB,WAAW;IAgBzB,IAAI,KAAK,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAO/C;IAEM,UAAU,IAAI,OAAO;IAIrB,WAAW,IAAI,OAAO;IAItB,gBAAgB,IAAI,aAAa,CAAC,CAAC,CAAC;IAYpC,iBAAiB,IAAI,WAAW,CAAC,GAAG,CAAC;IAYrC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,IAAI;IASjC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKvC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAK7B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKzD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CAI5C"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ORMType, } from "./types";
|
|
2
|
-
import {
|
|
3
|
-
import { SequelizeAdapter } from "../orm/adapters/sequelize-adapter";
|
|
2
|
+
import { loadMongooseAdapter, loadSequelizeAdapter, } from "../orm/adapter-loader";
|
|
4
3
|
export * from "./types";
|
|
5
4
|
const isMongooseConfig = (config) => {
|
|
6
5
|
return config.type === ORMType.Mongoose;
|
|
@@ -10,52 +9,83 @@ const isSequelizeConfig = (config) => {
|
|
|
10
9
|
};
|
|
11
10
|
export class BaseRepository {
|
|
12
11
|
adapter;
|
|
12
|
+
ormType;
|
|
13
|
+
config;
|
|
14
|
+
initPromise;
|
|
13
15
|
constructor(config) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
this.ormType = config.type;
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
async ensureInitialized() {
|
|
20
|
+
if (this.adapter)
|
|
21
|
+
return;
|
|
22
|
+
if (!this.initPromise) {
|
|
23
|
+
this.initPromise = this.loadAdapter();
|
|
24
|
+
}
|
|
25
|
+
await this.initPromise;
|
|
26
|
+
}
|
|
27
|
+
async loadAdapter() {
|
|
28
|
+
if (isMongooseConfig(this.config)) {
|
|
29
|
+
this.adapter = await loadMongooseAdapter(this.config);
|
|
16
30
|
}
|
|
17
|
-
else if (isSequelizeConfig(config)) {
|
|
18
|
-
this.adapter =
|
|
31
|
+
else if (isSequelizeConfig(this.config)) {
|
|
32
|
+
this.adapter = (await loadSequelizeAdapter(this.config));
|
|
19
33
|
}
|
|
20
34
|
else {
|
|
21
|
-
const exhaustive = config;
|
|
35
|
+
const exhaustive = this.config;
|
|
22
36
|
throw new Error(`Invalid repository configuration. Received: ${JSON.stringify(exhaustive)}`);
|
|
23
37
|
}
|
|
24
38
|
}
|
|
25
39
|
get model() {
|
|
40
|
+
if (!this.adapter) {
|
|
41
|
+
throw new Error("Repository not initialized. Call an async method first or await repository.ensureInitialized()");
|
|
42
|
+
}
|
|
26
43
|
return this.adapter.model;
|
|
27
44
|
}
|
|
28
45
|
isMongoose() {
|
|
29
|
-
return this.
|
|
46
|
+
return this.ormType === ORMType.Mongoose;
|
|
30
47
|
}
|
|
31
48
|
isSequelize() {
|
|
32
|
-
return this.
|
|
49
|
+
return this.ormType === ORMType.Sequelize;
|
|
33
50
|
}
|
|
34
51
|
getMongooseModel() {
|
|
52
|
+
if (!this.adapter) {
|
|
53
|
+
throw new Error("Repository not initialized. Call an async method first or await repository.ensureInitialized()");
|
|
54
|
+
}
|
|
35
55
|
if (!this.isMongoose()) {
|
|
36
56
|
throw new Error("Repository is not using Mongoose");
|
|
37
57
|
}
|
|
38
58
|
return this.adapter.model;
|
|
39
59
|
}
|
|
40
60
|
getSequelizeModel() {
|
|
61
|
+
if (!this.adapter) {
|
|
62
|
+
throw new Error("Repository not initialized. Call an async method first or await repository.ensureInitialized()");
|
|
63
|
+
}
|
|
41
64
|
if (!this.isSequelize()) {
|
|
42
65
|
throw new Error("Repository is not using Sequelize");
|
|
43
66
|
}
|
|
44
67
|
return this.adapter.model;
|
|
45
68
|
}
|
|
46
69
|
toLean(input) {
|
|
70
|
+
if (!this.adapter) {
|
|
71
|
+
throw new Error("Repository not initialized. Call an async method first or await repository.ensureInitialized()");
|
|
72
|
+
}
|
|
47
73
|
return this.adapter.toLean(input);
|
|
48
74
|
}
|
|
49
75
|
async findById(id) {
|
|
76
|
+
await this.ensureInitialized();
|
|
50
77
|
return this.adapter.findById(id);
|
|
51
78
|
}
|
|
52
79
|
async create(entity) {
|
|
80
|
+
await this.ensureInitialized();
|
|
53
81
|
return this.adapter.create(entity);
|
|
54
82
|
}
|
|
55
83
|
async update(id, update) {
|
|
84
|
+
await this.ensureInitialized();
|
|
56
85
|
return this.adapter.update(id, update);
|
|
57
86
|
}
|
|
58
87
|
async delete(id) {
|
|
88
|
+
await this.ensureInitialized();
|
|
59
89
|
return this.adapter.delete(id);
|
|
60
90
|
}
|
|
61
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract.js","sourceRoot":"./src/","sources":["service/architecture/infrastructure/repositories/abstract.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,OAAO,GACR,MAAM,SAAS,CAAC;AACjB,OAAO,
|
|
1
|
+
{"version":3,"file":"abstract.js","sourceRoot":"./src/","sources":["service/architecture/infrastructure/repositories/abstract.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Model as MongooseModel } from \"mongoose\";\nimport type { Model, ModelStatic } from \"sequelize\";\nimport {\n BaseRepositoryConfig,\n Repository,\n MongooseRepositoryConfig,\n SequelizeRepositoryConfig,\n ORMAdapter,\n ORMType,\n} from \"./types\";\nimport {\n loadMongooseAdapter,\n loadSequelizeAdapter,\n} from \"../orm/adapter-loader\";\n\nexport * from \"./types\";\n\n/**\n * Type guard to check if config is for Mongoose\n */\nconst isMongooseConfig = <D>(\n config: BaseRepositoryConfig<D>,\n): config is MongooseRepositoryConfig<D> => {\n return config.type === ORMType.Mongoose;\n};\n\n/**\n * Type guard to check if config is for Sequelize\n */\nconst isSequelizeConfig = <D extends Model>(\n config: BaseRepositoryConfig<D>,\n): config is SequelizeRepositoryConfig<D> => {\n return config.type === ORMType.Sequelize;\n};\n\n/**\n * BaseRepository - Abstract base class for all repositories\n *\n * Supports multiple ORMs (Mongoose, Sequelize) through adapter pattern.\n * Adapters are lazy-loaded - only the ORM you use gets imported.\n * This allows projects to install only one ORM without unused dependencies.\n *\n * Uses lazy initialization to support ESM dynamic imports while maintaining\n * backward compatibility with synchronous constructors.\n */\nexport abstract class BaseRepository<D, I, O> implements Repository<D, I, O> {\n private adapter?: ORMAdapter<D, I, O>;\n private readonly ormType: ORMType;\n private readonly config: BaseRepositoryConfig<D>;\n private initPromise?: Promise<void>;\n\n constructor(config: BaseRepositoryConfig<D>) {\n this.ormType = config.type;\n this.config = config;\n }\n\n /**\n * Ensures the adapter is initialized before any operation\n * Uses a promise to prevent multiple concurrent initializations\n */\n private async ensureInitialized(): Promise<void> {\n if (this.adapter) return;\n\n if (!this.initPromise) {\n this.initPromise = this.loadAdapter();\n }\n\n await this.initPromise;\n }\n\n /**\n * Loads the appropriate ORM adapter based on configuration\n */\n private async loadAdapter(): Promise<void> {\n if (isMongooseConfig<D>(this.config)) {\n this.adapter = await loadMongooseAdapter<D, I, O>(this.config);\n } else if (isSequelizeConfig(this.config)) {\n // Type assertion needed here because D could be either Mongoose or Sequelize model\n this.adapter = (await loadSequelizeAdapter<Model, I, O>(\n this.config,\n )) as ORMAdapter<D, I, O>;\n } else {\n const exhaustive: never = this.config;\n throw new Error(\n `Invalid repository configuration. Received: ${JSON.stringify(exhaustive)}`,\n );\n }\n }\n\n get model(): MongooseModel<D> | ModelStatic<any> {\n if (!this.adapter) {\n throw new Error(\n \"Repository not initialized. Call an async method first or await repository.ensureInitialized()\",\n );\n }\n return this.adapter.model;\n }\n\n public isMongoose(): boolean {\n return this.ormType === ORMType.Mongoose;\n }\n\n public isSequelize(): boolean {\n return this.ormType === ORMType.Sequelize;\n }\n\n public getMongooseModel(): MongooseModel<D> {\n if (!this.adapter) {\n throw new Error(\n \"Repository not initialized. Call an async method first or await repository.ensureInitialized()\",\n );\n }\n if (!this.isMongoose()) {\n throw new Error(\"Repository is not using Mongoose\");\n }\n return this.adapter.model as MongooseModel<D>;\n }\n\n public getSequelizeModel(): ModelStatic<any> {\n if (!this.adapter) {\n throw new Error(\n \"Repository not initialized. Call an async method first or await repository.ensureInitialized()\",\n );\n }\n if (!this.isSequelize()) {\n throw new Error(\"Repository is not using Sequelize\");\n }\n return this.adapter.model as ModelStatic<any>;\n }\n\n public toLean(input: unknown): O | null {\n if (!this.adapter) {\n throw new Error(\n \"Repository not initialized. Call an async method first or await repository.ensureInitialized()\",\n );\n }\n return this.adapter.toLean(input);\n }\n\n async findById(id: string): Promise<O | null> {\n await this.ensureInitialized();\n return this.adapter!.findById(id);\n }\n\n async create(entity: I): Promise<O> {\n await this.ensureInitialized();\n return this.adapter!.create(entity);\n }\n\n async update(id: string, update: Partial<I>): Promise<O | null> {\n await this.ensureInitialized();\n return this.adapter!.update(id, update);\n }\n\n async delete(id: string): Promise<O | null> {\n await this.ensureInitialized();\n return this.adapter!.delete(id);\n }\n}\n"]}
|