@sentzunhat/zacatl 0.0.20 → 0.0.21
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 +16 -0
- 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 +25 -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 +3 -2
- package/build/service/architecture/infrastructure/repositories/abstract.d.ts.map +1 -1
- package/build/service/architecture/infrastructure/repositories/abstract.js +7 -6
- package/build/service/architecture/infrastructure/repositories/abstract.js.map +1 -1
- package/build/test/tsconfig.tsbuildinfo +1 -1
- package/package.json +50 -7
- package/src/index.ts +3 -0
- package/src/orm-exports.ts +23 -0
- package/src/service/architecture/infrastructure/orm/adapter-loader.ts +52 -0
- package/src/service/architecture/infrastructure/orm/adapters/mongoose-adapter.ts +10 -11
- package/src/service/architecture/infrastructure/repositories/abstract.ts +21 -14
package/package.json
CHANGED
|
@@ -4,8 +4,36 @@
|
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"module": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
|
-
"version": "0.0.
|
|
7
|
+
"version": "0.0.21",
|
|
8
8
|
"packageManager": "npm@10.9.0",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./build/index.js",
|
|
12
|
+
"types": "./build/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./infrastructure": {
|
|
15
|
+
"import": "./build/service/architecture/infrastructure/repositories/abstract.js",
|
|
16
|
+
"types": "./build/service/architecture/infrastructure/repositories/abstract.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./domain": {
|
|
19
|
+
"import": "./build/service/architecture/domain/index.js",
|
|
20
|
+
"types": "./build/service/architecture/domain/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./application": {
|
|
23
|
+
"import": "./build/service/architecture/application/index.js",
|
|
24
|
+
"types": "./build/service/architecture/application/index.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./errors": {
|
|
27
|
+
"import": "./build/error/index.js",
|
|
28
|
+
"types": "./build/error/index.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"./config": {
|
|
31
|
+
"import": "./build/configuration/index.js",
|
|
32
|
+
"types": "./build/configuration/index.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./build/*": "./build/*",
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
9
37
|
"repository": {
|
|
10
38
|
"type": "git",
|
|
11
39
|
"url": "https://github.com/sentzunhat/zacatl.git"
|
|
@@ -70,9 +98,14 @@
|
|
|
70
98
|
"test": "NODE_ENV=test ENV=test vitest run",
|
|
71
99
|
"test:watch": "NODE_ENV=test ENV=test vitest",
|
|
72
100
|
"test:coverage": "npm run test -- --coverage",
|
|
101
|
+
"test:bun": "bun test",
|
|
102
|
+
"test:node": "vitest run",
|
|
73
103
|
"type:check": "tsc -p ./tsconfig.json && tsc -p test/tsconfig.json",
|
|
74
104
|
"lint": "DEBUG=eslint:cli-engine bun eslint .",
|
|
75
|
-
"
|
|
105
|
+
"prepublish": "npm run test:coverage && npm run type:check && npm run lint && npm run build",
|
|
106
|
+
"publish:latest": "npm run prepublish && npm publish --access public --tag latest",
|
|
107
|
+
"publish:otp": "npm run prepublish && npm publish --access public --tag latest --otp",
|
|
108
|
+
"publish:dry": "npm run prepublish && npm publish --dry-run"
|
|
76
109
|
},
|
|
77
110
|
"devDependencies": {
|
|
78
111
|
"@eslint/eslintrc": "^3.3.3",
|
|
@@ -102,6 +135,21 @@
|
|
|
102
135
|
"README.md",
|
|
103
136
|
"LICENSE"
|
|
104
137
|
],
|
|
138
|
+
"peerDependencies": {
|
|
139
|
+
"mongoose": "^9.0.0",
|
|
140
|
+
"sequelize": "^6.0.0"
|
|
141
|
+
},
|
|
142
|
+
"peerDependenciesMeta": {
|
|
143
|
+
"mongoose": {
|
|
144
|
+
"optional": true
|
|
145
|
+
},
|
|
146
|
+
"sequelize": {
|
|
147
|
+
"optional": true
|
|
148
|
+
},
|
|
149
|
+
"better-sqlite3": {
|
|
150
|
+
"optional": true
|
|
151
|
+
}
|
|
152
|
+
},
|
|
105
153
|
"dependencies": {
|
|
106
154
|
"@fastify/http-proxy": "^11.4.1",
|
|
107
155
|
"@fastify/static": "^8.3.0",
|
|
@@ -124,11 +172,6 @@
|
|
|
124
172
|
"uuid": "^13.0.0",
|
|
125
173
|
"zod": "^4.3.6"
|
|
126
174
|
},
|
|
127
|
-
"peerDependenciesMeta": {
|
|
128
|
-
"better-sqlite3": {
|
|
129
|
-
"optional": true
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
175
|
"optionalDependencies": {
|
|
133
176
|
"@types/better-sqlite3": "^7.6.13",
|
|
134
177
|
"better-sqlite3": "^12.6.2"
|
package/src/index.ts
CHANGED
|
@@ -30,5 +30,8 @@ export type { DependencyContainer } from "tsyringe";
|
|
|
30
30
|
export { z } from "zod";
|
|
31
31
|
export type { ZodSchema, ZodType, ZodError } from "zod";
|
|
32
32
|
|
|
33
|
+
// Re-export ORMs (included as dependencies)
|
|
34
|
+
export * from "./orm-exports";
|
|
35
|
+
|
|
33
36
|
// Note: TypeScript utility types (Partial, Required, Readonly, etc.)
|
|
34
37
|
// are globally available and don't need re-export
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export ORM dependencies for convenience
|
|
3
|
+
* These are included as dependencies (currently) for backward compatibility
|
|
4
|
+
* Future versions may move them to pure peer dependencies
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Mongoose exports - full re-export
|
|
8
|
+
export {
|
|
9
|
+
default as mongoose,
|
|
10
|
+
Mongoose,
|
|
11
|
+
Schema,
|
|
12
|
+
Model,
|
|
13
|
+
Document,
|
|
14
|
+
connect,
|
|
15
|
+
connection,
|
|
16
|
+
} from "mongoose";
|
|
17
|
+
|
|
18
|
+
// Sequelize exports - full re-export
|
|
19
|
+
export { Sequelize, Model as SequelizeModel, DataTypes, Op } from "sequelize";
|
|
20
|
+
|
|
21
|
+
// Type-only exports for convenience
|
|
22
|
+
export type { Model as MongooseModel } from "mongoose";
|
|
23
|
+
export type { ModelStatic, Options as SequelizeOptions } from "sequelize";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Model } from "sequelize";
|
|
2
|
+
import type {
|
|
3
|
+
MongooseRepositoryConfig,
|
|
4
|
+
SequelizeRepositoryConfig,
|
|
5
|
+
ORMAdapter,
|
|
6
|
+
} from "../repositories/types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Loads MongooseAdapter dynamically - only when needed
|
|
10
|
+
* Throws helpful error if mongoose is not installed
|
|
11
|
+
*/
|
|
12
|
+
export function loadMongooseAdapter<D, I, O>(
|
|
13
|
+
config: MongooseRepositoryConfig<D>,
|
|
14
|
+
): ORMAdapter<D, I, O> {
|
|
15
|
+
try {
|
|
16
|
+
// Dynamic import - only loads when Mongoose is actually used
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
18
|
+
const adapters =
|
|
19
|
+
require("./adapters/mongoose-adapter") as typeof import("./adapters/mongoose-adapter");
|
|
20
|
+
return new adapters.MongooseAdapter<D, I, O>(config);
|
|
21
|
+
} catch (error: any) {
|
|
22
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"Mongoose is not installed. Install it with: npm install mongoose",
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Loads SequelizeAdapter dynamically - only when needed
|
|
33
|
+
* Throws helpful error if sequelize is not installed
|
|
34
|
+
*/
|
|
35
|
+
export function loadSequelizeAdapter<D extends Model, I, O>(
|
|
36
|
+
config: SequelizeRepositoryConfig<D>,
|
|
37
|
+
): ORMAdapter<D, I, O> {
|
|
38
|
+
try {
|
|
39
|
+
// Dynamic import - only loads when Sequelize is actually used
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
41
|
+
const adapters =
|
|
42
|
+
require("./adapters/sequelize-adapter") as typeof import("./adapters/sequelize-adapter");
|
|
43
|
+
return new adapters.SequelizeAdapter<D, I, O>(config);
|
|
44
|
+
} catch (error: any) {
|
|
45
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"Sequelize is not installed. Install it with: npm install sequelize",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
Model as MongooseModel,
|
|
4
|
-
Mongoose,
|
|
5
|
-
} from "mongoose";
|
|
1
|
+
import type { Model as MongooseModel } from "mongoose";
|
|
2
|
+
import { Mongoose } from "mongoose";
|
|
6
3
|
import { v4 as uuidv4 } from "uuid";
|
|
7
4
|
import { container } from "tsyringe";
|
|
8
5
|
import type {
|
|
@@ -14,9 +11,11 @@ import type {
|
|
|
14
11
|
/**
|
|
15
12
|
* MongooseAdapter - Handles Mongoose-specific ORM operations
|
|
16
13
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* ID normalization
|
|
14
|
+
* Provides consistent interface for repository layer with:
|
|
15
|
+
* - Document transformation
|
|
16
|
+
* - ID normalization
|
|
17
|
+
* - Timestamp management
|
|
18
|
+
* - Connection instance from DI container
|
|
20
19
|
*/
|
|
21
20
|
export class MongooseAdapter<D, I, O> implements ORMAdapter<D, I, O> {
|
|
22
21
|
public readonly model: MongooseModel<D>;
|
|
@@ -24,9 +23,9 @@ export class MongooseAdapter<D, I, O> implements ORMAdapter<D, I, O> {
|
|
|
24
23
|
|
|
25
24
|
constructor(config: MongooseRepositoryConfig<D>) {
|
|
26
25
|
this.config = config;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
// Get mongoose instance from DI container - allows per-database configuration
|
|
27
|
+
// Connection strings should be set up before repository instantiation
|
|
28
|
+
const mongoose = container.resolve<Mongoose>(Mongoose);
|
|
30
29
|
|
|
31
30
|
const { name, schema } = this.config;
|
|
32
31
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Model as MongooseModel } from "mongoose";
|
|
2
|
-
import { Model, ModelStatic } from "sequelize";
|
|
1
|
+
import type { Model as MongooseModel } from "mongoose";
|
|
2
|
+
import type { Model, ModelStatic } from "sequelize";
|
|
3
3
|
import {
|
|
4
4
|
BaseRepositoryConfig,
|
|
5
5
|
Repository,
|
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
ORMAdapter,
|
|
9
9
|
ORMType,
|
|
10
10
|
} from "./types";
|
|
11
|
-
import {
|
|
12
|
-
|
|
11
|
+
import {
|
|
12
|
+
loadMongooseAdapter,
|
|
13
|
+
loadSequelizeAdapter,
|
|
14
|
+
} from "../orm/adapter-loader";
|
|
13
15
|
|
|
14
16
|
export * from "./types";
|
|
15
17
|
|
|
@@ -34,22 +36,27 @@ const isSequelizeConfig = <D extends Model>(
|
|
|
34
36
|
/**
|
|
35
37
|
* BaseRepository - Abstract base class for all repositories
|
|
36
38
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
39
|
+
* Supports multiple ORMs (Mongoose, Sequelize) through adapter pattern.
|
|
40
|
+
* Adapters are lazy-loaded - only the ORM you use gets imported.
|
|
41
|
+
* This allows projects to install only one ORM without unused dependencies.
|
|
40
42
|
*/
|
|
41
43
|
export abstract class BaseRepository<D, I, O> implements Repository<D, I, O> {
|
|
42
44
|
private adapter: ORMAdapter<D, I, O>;
|
|
45
|
+
private readonly ormType: ORMType;
|
|
43
46
|
|
|
44
47
|
constructor(config: BaseRepositoryConfig<D>) {
|
|
48
|
+
this.ormType = config.type;
|
|
49
|
+
|
|
45
50
|
if (isMongooseConfig<D>(config)) {
|
|
46
|
-
|
|
47
|
-
this.adapter = new MongooseAdapter<D, I, O>(config);
|
|
51
|
+
this.adapter = loadMongooseAdapter<D, I, O>(config);
|
|
48
52
|
} else if (isSequelizeConfig(config)) {
|
|
49
|
-
//
|
|
50
|
-
this.adapter =
|
|
53
|
+
// Type assertion needed here because D could be either Mongoose or Sequelize model
|
|
54
|
+
this.adapter = loadSequelizeAdapter<Model, I, O>(config) as ORMAdapter<
|
|
55
|
+
D,
|
|
56
|
+
I,
|
|
57
|
+
O
|
|
58
|
+
>;
|
|
51
59
|
} else {
|
|
52
|
-
// Exhaustiveness check - should never reach here with proper types
|
|
53
60
|
const exhaustive: never = config;
|
|
54
61
|
throw new Error(
|
|
55
62
|
`Invalid repository configuration. Received: ${JSON.stringify(exhaustive)}`,
|
|
@@ -62,11 +69,11 @@ export abstract class BaseRepository<D, I, O> implements Repository<D, I, O> {
|
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
public isMongoose(): boolean {
|
|
65
|
-
return this.
|
|
72
|
+
return this.ormType === ORMType.Mongoose;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
public isSequelize(): boolean {
|
|
69
|
-
return this.
|
|
76
|
+
return this.ormType === ORMType.Sequelize;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
public getMongooseModel(): MongooseModel<D> {
|