@sentzunhat/zacatl 0.0.12 → 0.0.13

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@sentzunhat/zacatl",
3
3
  "main": "src/index.ts",
4
4
  "module": "src/index.ts",
5
- "version": "0.0.12",
5
+ "version": "0.0.13",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/sentzunhat/zacatl.git"
@@ -65,6 +65,7 @@
65
65
  "@types/config": "^3.3.5",
66
66
  "@types/i18n": "^0.13.12",
67
67
  "@types/node": "^22.7.4",
68
+ "@types/sequelize": "^4.28.20",
68
69
  "@types/uuid": "^10.0.0",
69
70
  "@typescript-eslint/parser": "^8.29.0",
70
71
  "@vitest/coverage-istanbul": "^3.1.1",
@@ -84,6 +85,7 @@
84
85
  "i18n": "^0.15.1",
85
86
  "mongodb-memory-server": "^10.1.4",
86
87
  "mongoose": "^8.15.0",
88
+ "sequelize": "^6.37.5",
87
89
  "pino": "^9.7.0",
88
90
  "pino-pretty": "^13.0.0",
89
91
  "reflect-metadata": "^0.2.2",
package/src/index.ts CHANGED
@@ -3,4 +3,5 @@ export * from "./configuration";
3
3
  export * from "./utils";
4
4
  export * from "./error";
5
5
  export * from "./micro-service";
6
+ export { MicroService } from "./micro-service";
6
7
  export * from "./logs";
package/src/logs.ts CHANGED
@@ -31,50 +31,44 @@ const defaultLogger: pino.BaseLogger = pino({
31
31
 
32
32
  export type LoggerInput =
33
33
  | {
34
- logData?: unknown;
35
- metadata?: unknown;
34
+ data?: unknown;
35
+ details?: unknown;
36
36
  }
37
37
  | undefined;
38
38
 
39
39
  const logger = {
40
40
  log: (message: string, input?: LoggerInput): void => {
41
41
  console.log(message, {
42
- logData: input?.logData,
43
- metadata: input?.metadata,
42
+ data: input?.data,
43
+ details: input?.details,
44
44
  });
45
45
  },
46
46
 
47
47
  info: (message: string, input?: LoggerInput): void => {
48
- defaultLogger.info(
49
- { logData: input?.logData, metadata: input?.metadata },
50
- message
51
- );
48
+ defaultLogger.info({ data: input?.data, details: input?.details }, message);
52
49
  },
53
50
 
54
51
  trace: (message: string, input?: LoggerInput): void => {
55
52
  defaultLogger.trace(
56
- { logData: input?.logData, metadata: input?.metadata },
53
+ { data: input?.data, details: input?.details },
57
54
  message
58
55
  );
59
56
  },
60
57
 
61
58
  warn: (message: string, input?: LoggerInput): void => {
62
- defaultLogger.warn(
63
- { logData: input?.logData, metadata: input?.metadata },
64
- message
65
- );
59
+ defaultLogger.warn({ data: input?.data, details: input?.details }, message);
66
60
  },
67
61
 
68
62
  error: (message: string, input?: LoggerInput): void => {
69
63
  defaultLogger.error(
70
- { logData: input?.logData, metadata: input?.metadata },
64
+ { data: input?.data, details: input?.details },
71
65
  message
72
66
  );
73
67
  },
74
68
 
75
69
  fatal: (message: string, input?: LoggerInput): void => {
76
70
  defaultLogger.fatal(
77
- { logData: input?.logData, metadata: input?.metadata },
71
+ { data: input?.data, details: input?.details },
78
72
  message
79
73
  );
80
74
  },
@@ -4,8 +4,12 @@ import path from "path";
4
4
  import { AbstractArchitecture } from "../architecture";
5
5
  import { HookHandler, RouteHandler } from "./entry-points/rest";
6
6
 
7
- export type ApplicationHookHandlers = Array<new () => HookHandler>;
8
- export type ApplicationRouteHandlers = Array<new () => RouteHandler>;
7
+ export type ApplicationHookHandlers = Array<
8
+ new (...args: unknown[]) => HookHandler
9
+ >;
10
+ export type ApplicationRouteHandlers = Array<
11
+ new (...args: unknown[]) => RouteHandler
12
+ >;
9
13
 
10
14
  export type ApplicationEntryPoints = {
11
15
  rest: {
@@ -6,8 +6,9 @@ export type Handler<
6
6
  TBody = void,
7
7
  TQuerystring = void,
8
8
  TParams = void,
9
- THeaders = void
9
+ THeaders = void,
10
+ TReply = unknown
10
11
  > = (
11
12
  request: Request<TBody, TQuerystring, TParams, THeaders>,
12
13
  reply: FastifyReply
13
- ) => Promise<void>;
14
+ ) => Promise<TReply>;
@@ -1,7 +1,7 @@
1
1
  import { AbstractArchitecture } from "../architecture";
2
2
 
3
3
  export type ConfigDomain = {
4
- providers: Array<new () => unknown>;
4
+ providers: Array<new (...args: unknown[]) => unknown>;
5
5
  };
6
6
 
7
7
  export class Domain extends AbstractArchitecture {
@@ -1,7 +1,7 @@
1
1
  import { AbstractArchitecture } from "../architecture";
2
2
 
3
3
  export type ConfigInfrastructure = {
4
- repositories: Array<new () => unknown>;
4
+ repositories: Array<new (...args: unknown[]) => unknown>;
5
5
  };
6
6
 
7
7
  export class Infrastructure extends AbstractArchitecture {
@@ -1,176 +1,68 @@
1
- import importedMongoose, {
2
- connection,
3
- IfAny,
4
- Model,
5
- Mongoose,
6
- Document,
7
- Schema,
8
- Default__v,
9
- Require_id,
10
- ObjectId,
11
- } from "mongoose";
12
- import { v4 as uuidv4 } from "uuid";
13
- import { container } from "tsyringe";
14
-
15
- export type BaseRepositoryConfig<D> = {
16
- name?: string;
17
- schema: Schema<D>;
18
- };
19
-
20
- export type WithMongooseMeta<T> = Default__v<Require_id<T>>;
21
-
22
- export type MongooseDocument<Db> = Document<
23
- ObjectId,
24
- {},
25
- Db,
26
- Record<string, string>
27
- > &
28
- WithMongooseMeta<Db>;
29
-
30
- export type LeanWithMeta<T> = WithMongooseMeta<T> & {
31
- id: string;
32
- createdAt: Date;
33
- updatedAt: Date;
34
- };
35
-
36
- export type LeanDocument<T> = T & {
37
- id: string;
38
- createdAt: Date;
39
- updatedAt: Date;
40
- };
41
-
42
- export type MongooseDoc<Db> = IfAny<
43
- MongooseDocument<Db>,
44
- MongooseDocument<Db>,
45
- MongooseDocument<Db>
46
- >;
47
-
48
- export type ToLeanInput<D, T> =
49
- | MongooseDoc<D>
50
- | LeanDocument<T>
51
- | null
52
- | undefined;
53
-
54
- // D - Document, meant for Database representation
55
- // T - Type, meant for TypeScript representation
56
- export type Repository<D, T> = {
57
- model: Model<D>;
58
-
59
- toLean(input: ToLeanInput<D, T>): LeanDocument<T> | null;
60
- findById(id: string): Promise<LeanDocument<T> | null>;
61
- create(entity: D): Promise<LeanDocument<T>>;
62
- update(id: string, update: Partial<D>): Promise<LeanDocument<T> | null>;
63
- delete(id: string): Promise<LeanDocument<T> | null>;
64
- };
1
+ import { Model as MongooseModel } from "mongoose";
2
+ import { ModelCtor } from "sequelize";
3
+ import {
4
+ BaseRepositoryConfig,
5
+ Repository,
6
+ LeanDocument,
7
+ ToLeanInput,
8
+ MongooseRepositoryConfig,
9
+ } from "./types";
10
+ import { MongooseRepository } from "./mongoose";
11
+ import { SequelizeRepository } from "./sequelize";
12
+
13
+ export * from "./types";
65
14
 
66
15
  export abstract class BaseRepository<D, T> implements Repository<D, T> {
67
- public readonly model: Model<D>;
68
- private readonly config: BaseRepositoryConfig<D>;
16
+ private implementation: Repository<D, T>;
69
17
 
70
18
  constructor(config: BaseRepositoryConfig<D>) {
71
- this.config = config;
72
- const mongoose = connection.db?.databaseName
73
- ? importedMongoose
74
- : container.resolve<Mongoose>(Mongoose);
75
-
76
- const { name, schema } = this.config;
77
-
78
- if (name) {
79
- this.model = mongoose.model<D>(name, schema);
19
+ if (config.type === "mongoose") {
20
+ this.implementation = new MongooseRepository(config);
21
+ } else if (config.type === "sequelize") {
22
+ this.implementation = new SequelizeRepository(
23
+ config as any
24
+ ) as unknown as Repository<D, T>;
80
25
  } else {
81
- this.model = mongoose.model<D>(uuidv4(), schema);
26
+ // Backward compatibility: if type is missing but schema is present, assume Mongoose
27
+ if ((config as any).schema) {
28
+ const mongooseConfig: MongooseRepositoryConfig<D> = {
29
+ type: "mongoose",
30
+ name: (config as any).name,
31
+ schema: (config as any).schema,
32
+ };
33
+ this.implementation = new MongooseRepository(mongooseConfig);
34
+ } else {
35
+ throw new Error(
36
+ "Invalid repository configuration: 'type' must be 'mongoose' or 'sequelize'"
37
+ );
38
+ }
82
39
  }
40
+ }
83
41
 
84
- this.model.createCollection();
85
- this.model.createIndexes();
86
- this.model.init();
42
+ get model(): MongooseModel<D> | ModelCtor<any> {
43
+ return this.implementation.model;
87
44
  }
88
45
 
89
- /**
90
- * Ensures the returned document has the correct id, createdAt, and updatedAt fields.
91
- * Accepts a Mongoose document, a plain object, or a result from .lean().
92
- */
93
46
  public toLean(input: ToLeanInput<D, T>): LeanDocument<T> | null {
94
- if (!input) {
95
- return null;
96
- }
97
-
98
- let base: LeanWithMeta<T>;
99
-
100
- if (typeof (input as MongooseDoc<D>).toObject === "function") {
101
- base = (input as MongooseDoc<D>).toObject<LeanDocument<T>>({
102
- virtuals: true,
103
- });
104
- } else {
105
- base = input as LeanWithMeta<T>;
106
- }
107
-
108
- const result: LeanDocument<T> = {
109
- ...(base as T), // trust only known keys from T
110
- id:
111
- typeof base.id === "string"
112
- ? base.id
113
- : typeof base._id === "string"
114
- ? base._id
115
- : base._id !== undefined
116
- ? String(base._id)
117
- : "",
118
- createdAt:
119
- base.createdAt instanceof Date
120
- ? base.createdAt
121
- : base.createdAt
122
- ? new Date(base.createdAt as string | number)
123
- : new Date(),
124
- updatedAt:
125
- base.updatedAt instanceof Date
126
- ? base.updatedAt
127
- : base.updatedAt
128
- ? new Date(base.updatedAt as string | number)
129
- : new Date(),
130
- };
131
-
132
- return result;
47
+ return this.implementation.toLean(input);
133
48
  }
134
49
 
135
50
  async findById(id: string): Promise<LeanDocument<T> | null> {
136
- const entity = await this.model
137
- .findById(id)
138
- .lean<LeanDocument<T>>({ virtuals: true })
139
- .exec();
140
-
141
- return this.toLean(entity);
51
+ return this.implementation.findById(id);
142
52
  }
143
53
 
144
54
  async create(entity: D): Promise<LeanDocument<T>> {
145
- const document = await this.model.create<D>(entity);
146
-
147
- const leanDocument = this.toLean(document as MongooseDoc<D>);
148
-
149
- if (!leanDocument) {
150
- throw new Error("failed to create document");
151
- }
152
-
153
- return leanDocument;
55
+ return this.implementation.create(entity);
154
56
  }
155
57
 
156
58
  async update(
157
59
  id: string,
158
60
  update: Partial<D>
159
61
  ): Promise<LeanDocument<T> | null> {
160
- const entity = await this.model
161
- .findByIdAndUpdate(id, update, { new: true })
162
- .lean<LeanDocument<T>>({ virtuals: true })
163
- .exec();
164
-
165
- return this.toLean(entity);
62
+ return this.implementation.update(id, update);
166
63
  }
167
64
 
168
65
  async delete(id: string): Promise<LeanDocument<T> | null> {
169
- const entity = await this.model
170
- .findByIdAndDelete(id)
171
- .lean<LeanDocument<T>>({ virtuals: true })
172
- .exec();
173
-
174
- return this.toLean(entity);
66
+ return this.implementation.delete(id);
175
67
  }
176
68
  }
@@ -0,0 +1,124 @@
1
+ import importedMongoose, { connection, Model, Mongoose } from "mongoose";
2
+ import { v4 as uuidv4 } from "uuid";
3
+ import { container } from "tsyringe";
4
+ import {
5
+ Repository,
6
+ MongooseRepositoryConfig,
7
+ LeanDocument,
8
+ ToLeanInput,
9
+ LeanWithMeta,
10
+ MongooseDoc,
11
+ } from "./types";
12
+
13
+ export class MongooseRepository<D, T> implements Repository<D, T> {
14
+ public readonly model: Model<D>;
15
+ private readonly config: MongooseRepositoryConfig<D>;
16
+
17
+ constructor(config: MongooseRepositoryConfig<D>) {
18
+ this.config = config;
19
+ const mongoose = connection.db?.databaseName
20
+ ? importedMongoose
21
+ : container.resolve<Mongoose>(Mongoose);
22
+
23
+ const { name, schema } = this.config;
24
+
25
+ if (name) {
26
+ this.model = mongoose.model<D>(name, schema);
27
+ } else {
28
+ this.model = mongoose.model<D>(uuidv4(), schema);
29
+ }
30
+
31
+ this.model.createCollection();
32
+ this.model.createIndexes();
33
+ this.model.init();
34
+ }
35
+
36
+ public toLean(input: ToLeanInput<D, T>): LeanDocument<T> | null {
37
+ if (!input) {
38
+ return null;
39
+ }
40
+
41
+ let base: LeanWithMeta<T>;
42
+
43
+ if (
44
+ input &&
45
+ typeof input === "object" &&
46
+ "toObject" in input &&
47
+ typeof (input as any).toObject === "function"
48
+ ) {
49
+ base = (input as any).toObject({
50
+ virtuals: true,
51
+ }) as LeanWithMeta<T>;
52
+ } else {
53
+ base = input as LeanWithMeta<T>;
54
+ }
55
+
56
+ const result: LeanDocument<T> = {
57
+ ...(base as T),
58
+ id:
59
+ typeof base.id === "string"
60
+ ? base.id
61
+ : typeof base._id === "string"
62
+ ? base._id
63
+ : base._id !== undefined
64
+ ? String(base._id)
65
+ : "",
66
+ createdAt:
67
+ base.createdAt instanceof Date
68
+ ? base.createdAt
69
+ : base.createdAt
70
+ ? new Date(base.createdAt as string | number)
71
+ : new Date(),
72
+ updatedAt:
73
+ base.updatedAt instanceof Date
74
+ ? base.updatedAt
75
+ : base.updatedAt
76
+ ? new Date(base.updatedAt as string | number)
77
+ : new Date(),
78
+ };
79
+
80
+ return result;
81
+ }
82
+
83
+ async findById(id: string): Promise<LeanDocument<T> | null> {
84
+ const entity = await this.model
85
+ .findById(id)
86
+ .lean<LeanDocument<T>>({ virtuals: true })
87
+ .exec();
88
+
89
+ return this.toLean(entity);
90
+ }
91
+
92
+ async create(entity: D): Promise<LeanDocument<T>> {
93
+ const document = await this.model.create<D>(entity);
94
+
95
+ const leanDocument = this.toLean(document as MongooseDoc<D>);
96
+
97
+ if (!leanDocument) {
98
+ throw new Error("failed to create document");
99
+ }
100
+
101
+ return leanDocument;
102
+ }
103
+
104
+ async update(
105
+ id: string,
106
+ update: Partial<D>
107
+ ): Promise<LeanDocument<T> | null> {
108
+ const entity = await this.model
109
+ .findByIdAndUpdate(id, update, { new: true })
110
+ .lean<LeanDocument<T>>({ virtuals: true })
111
+ .exec();
112
+
113
+ return this.toLean(entity);
114
+ }
115
+
116
+ async delete(id: string): Promise<LeanDocument<T> | null> {
117
+ const entity = await this.model
118
+ .findByIdAndDelete(id)
119
+ .lean<LeanDocument<T>>({ virtuals: true })
120
+ .exec();
121
+
122
+ return this.toLean(entity);
123
+ }
124
+ }
@@ -0,0 +1,70 @@
1
+ import { Model, ModelCtor } from "sequelize";
2
+ import { Repository, SequelizeRepositoryConfig, LeanDocument } from "./types";
3
+
4
+ export class SequelizeRepository<D extends Model, T>
5
+ implements Repository<D, T>
6
+ {
7
+ public readonly model: ModelCtor<D>;
8
+
9
+ constructor(config: SequelizeRepositoryConfig<D>) {
10
+ this.model = config.model;
11
+ }
12
+
13
+ public toLean(input: any): LeanDocument<T> | null {
14
+ if (!input) return null;
15
+ const plain = input instanceof Model ? input.get({ plain: true }) : input;
16
+
17
+ // Ensure id, createdAt, updatedAt exist and are correct types
18
+ // This assumes the model has these fields.
19
+ return {
20
+ ...(plain as T),
21
+ id: String(plain.id || plain._id || ""),
22
+ createdAt: plain.createdAt ? new Date(plain.createdAt) : new Date(),
23
+ updatedAt: plain.updatedAt ? new Date(plain.updatedAt) : new Date(),
24
+ } as LeanDocument<T>;
25
+ }
26
+
27
+ async findById(id: string): Promise<LeanDocument<T> | null> {
28
+ const entity = await this.model.findByPk(id);
29
+ return this.toLean(entity);
30
+ }
31
+
32
+ async create(entity: D): Promise<LeanDocument<T>> {
33
+ const document = await this.model.create(entity as any);
34
+ return this.toLean(document) as LeanDocument<T>;
35
+ }
36
+
37
+ async update(
38
+ id: string,
39
+ update: Partial<D>
40
+ ): Promise<LeanDocument<T> | null> {
41
+ const [affectedCount] = await this.model.update(update as any, {
42
+ where: { id } as any,
43
+ });
44
+
45
+ if (affectedCount === 0) {
46
+ return null;
47
+ }
48
+
49
+ return this.findById(id);
50
+ }
51
+
52
+ async delete(id: string): Promise<LeanDocument<T> | null> {
53
+ const entity = await this.findById(id);
54
+ if (!entity) return null;
55
+
56
+ await this.model.destroy({
57
+ where: { id } as any,
58
+ });
59
+
60
+ return entity;
61
+ }
62
+ }
63
+ [
64
+ {
65
+ type: "image",
66
+ payload: {
67
+ attachment_id: "{{ $json.propertyName }}",
68
+ },
69
+ },
70
+ ];
@@ -0,0 +1,69 @@
1
+ import {
2
+ Document,
3
+ Model as MongooseModel,
4
+ Schema,
5
+ Default__v,
6
+ Require_id,
7
+ ObjectId,
8
+ IfAny,
9
+ } from "mongoose";
10
+ import { Model as SequelizeModel, ModelCtor, Model } from "sequelize";
11
+
12
+ export type WithMongooseMeta<T> = Default__v<Require_id<T>>;
13
+
14
+ export type MongooseDocument<Db> = Document<
15
+ ObjectId,
16
+ {},
17
+ Db,
18
+ Record<string, string>
19
+ > &
20
+ WithMongooseMeta<Db>;
21
+
22
+ export type LeanWithMeta<T> = WithMongooseMeta<T> & {
23
+ id: string;
24
+ createdAt: Date;
25
+ updatedAt: Date;
26
+ };
27
+
28
+ export type LeanDocument<T> = T & {
29
+ id: string;
30
+ createdAt: Date;
31
+ updatedAt: Date;
32
+ };
33
+
34
+ export type MongooseDoc<Db> = IfAny<
35
+ MongooseDocument<Db>,
36
+ MongooseDocument<Db>,
37
+ MongooseDocument<Db>
38
+ >;
39
+
40
+ export type ToLeanInput<D, T> =
41
+ | MongooseDoc<D>
42
+ | LeanDocument<T>
43
+ | null
44
+ | undefined;
45
+
46
+ export type MongooseRepositoryConfig<D> = {
47
+ type: "mongoose";
48
+ name?: string;
49
+ schema: Schema<D>;
50
+ };
51
+
52
+ export type SequelizeRepositoryConfig<D extends Model> = {
53
+ type: "sequelize";
54
+ model: ModelCtor<D>;
55
+ };
56
+
57
+ export type BaseRepositoryConfig<D> =
58
+ | MongooseRepositoryConfig<D>
59
+ | SequelizeRepositoryConfig<D extends Model ? D : never>;
60
+
61
+ export type Repository<D, T> = {
62
+ model: MongooseModel<D> | ModelCtor<SequelizeModel<any, any>>;
63
+
64
+ toLean(input: any): LeanDocument<T> | null;
65
+ findById(id: string): Promise<LeanDocument<T> | null>;
66
+ create(entity: D): Promise<LeanDocument<T>>;
67
+ update(id: string, update: Partial<D>): Promise<LeanDocument<T> | null>;
68
+ delete(id: string): Promise<LeanDocument<T> | null>;
69
+ };
@@ -3,6 +3,7 @@ import { FastifyInstance } from "fastify";
3
3
  import { ZodTypeProvider } from "fastify-type-provider-zod";
4
4
  import { container } from "tsyringe";
5
5
  import { Mongoose } from "mongoose";
6
+ import { Sequelize } from "sequelize";
6
7
 
7
8
  import { HookHandler, RouteHandler } from "../../application";
8
9
  import { CustomError } from "../../../../error";
@@ -37,9 +38,10 @@ type ServiceServer = {
37
38
 
38
39
  export enum DatabaseVendor {
39
40
  MONGOOSE = "MONGOOSE",
41
+ SEQUELIZE = "SEQUELIZE",
40
42
  }
41
43
 
42
- type DatabaseInstance = Mongoose;
44
+ type DatabaseInstance = Mongoose | Sequelize;
43
45
 
44
46
  type OnDatabaseConnectedFunction = Optional<
45
47
  (dbInstance: DatabaseInstance) => Promise<void> | void
@@ -126,7 +128,9 @@ export const strategiesForDatabaseVendor = {
126
128
  const { serviceName, database, connectionString, onDatabaseConnected } =
127
129
  input;
128
130
 
129
- if (!database || !database.connect) {
131
+ const mongoose = database as Mongoose;
132
+
133
+ if (!mongoose || !mongoose.connect) {
130
134
  throw new CustomError({
131
135
  message: "database instance is not provided",
132
136
  code: 500,
@@ -134,18 +138,45 @@ export const strategiesForDatabaseVendor = {
134
138
  });
135
139
  }
136
140
 
137
- await database.connect(connectionString, {
141
+ await mongoose.connect(connectionString, {
138
142
  dbName: serviceName,
139
143
  autoIndex: true,
140
144
  autoCreate: true,
141
145
  });
142
146
 
147
+ if (onDatabaseConnected) {
148
+ await onDatabaseConnected(mongoose);
149
+ }
150
+
151
+ container.register<Mongoose>(mongoose.constructor.name, {
152
+ useValue: mongoose,
153
+ });
154
+ },
155
+ [DatabaseVendor.SEQUELIZE]: async (input: {
156
+ serviceName: string;
157
+ database: DatabaseInstance;
158
+ connectionString: string;
159
+ onDatabaseConnected?: OnDatabaseConnectedFunction;
160
+ }) => {
161
+ const { database, onDatabaseConnected } = input;
162
+ const sequelize = database as Sequelize;
163
+
164
+ if (!sequelize || !sequelize.authenticate) {
165
+ throw new CustomError({
166
+ message: "database instance is not provided or invalid",
167
+ code: 500,
168
+ reason: "database instance not provided",
169
+ });
170
+ }
171
+
172
+ await sequelize.authenticate();
173
+
143
174
  if (onDatabaseConnected) {
144
175
  await onDatabaseConnected(database);
145
176
  }
146
177
 
147
- container.register<typeof database>(database.constructor.name, {
148
- useValue: database,
178
+ container.register<Sequelize>("Sequelize", {
179
+ useValue: sequelize,
149
180
  });
150
181
  },
151
182
  };
@@ -15,7 +15,7 @@ const schemaUserTest = new Schema<UserTest>({
15
15
  @singleton()
16
16
  class UserRepository extends BaseRepository<UserTest, UserTest> {
17
17
  constructor() {
18
- super({ name: "User", schema: schemaUserTest });
18
+ super({ type: "mongoose", name: "User", schema: schemaUserTest });
19
19
  }
20
20
  }
21
21
 
@@ -29,14 +29,14 @@ describe("BaseRepository", () => {
29
29
  });
30
30
 
31
31
  it("should create a model using the provided name and schema", async () => {
32
- expect(repository.model.modelName).toBe("User");
33
- expect(repository.model.schema).toBe(schemaUserTest);
32
+ expect((repository.model as any).modelName).toBe("User");
33
+ expect((repository.model as any).schema).toBe(schemaUserTest);
34
34
  });
35
35
 
36
36
  it("should call create() and return the created user document", async () => {
37
37
  const user = { name: "Alice" };
38
38
 
39
- const spyFunction = vi.spyOn(repository.model, "create");
39
+ const spyFunction = vi.spyOn(repository.model as any, "create");
40
40
 
41
41
  const result = await repository.create(user);
42
42
 
@@ -46,7 +46,7 @@ describe("BaseRepository", () => {
46
46
 
47
47
  it("should call findById() and return the user document", async () => {
48
48
  const user = await repository.create({ name: "Alice" });
49
- const spyFunction = vi.spyOn(repository.model, "findById");
49
+ const spyFunction = vi.spyOn(repository.model as any, "findById");
50
50
  const result = await repository.findById(user.id);
51
51
  expect(spyFunction).toHaveBeenNthCalledWith(1, user.id);
52
52
  expect(result).toMatchObject({ name: user.name });
@@ -58,7 +58,7 @@ describe("BaseRepository", () => {
58
58
 
59
59
  const update = { name: "Alice Updated" };
60
60
 
61
- const spyFunction = vi.spyOn(repository.model, "findByIdAndUpdate");
61
+ const spyFunction = vi.spyOn(repository.model as any, "findByIdAndUpdate");
62
62
 
63
63
  const result = await repository.update(user.id, update);
64
64
 
@@ -70,7 +70,7 @@ describe("BaseRepository", () => {
70
70
 
71
71
  it("should call delete() and return the deleted user document", async () => {
72
72
  const user = await repository.create({ name: "Alice" });
73
- const spyFunction = vi.spyOn(repository.model, "findByIdAndDelete");
73
+ const spyFunction = vi.spyOn(repository.model as any, "findByIdAndDelete");
74
74
  const result = await repository.delete(user.id);
75
75
  expect(spyFunction).toHaveBeenNthCalledWith(1, user.id);
76
76
  // Patch: allow for id only (ignore _id)