ballrush-core 0.6.1 → 0.6.2

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.
@@ -0,0 +1,64 @@
1
+ import { AchievementType } from "../types";
2
+ export type AchievementScope = "event" | "season" | "lifetime";
3
+ export interface AchievementTranslation {
4
+ title: string;
5
+ description: string;
6
+ }
7
+ export interface AchievementTranslations {
8
+ [language: string]: AchievementTranslation;
9
+ }
10
+ export declare class Achievement {
11
+ private readonly achievementId;
12
+ private readonly type;
13
+ private readonly scope;
14
+ private title;
15
+ private description;
16
+ private translations;
17
+ private icon;
18
+ private algorithm;
19
+ private isActive;
20
+ private createdAt;
21
+ private updatedAt;
22
+ private constructor();
23
+ static create(params: {
24
+ achievementId: string;
25
+ type: AchievementType;
26
+ scope: AchievementScope;
27
+ title: string;
28
+ description: string;
29
+ translations?: AchievementTranslations;
30
+ icon: string;
31
+ algorithm: string;
32
+ isActive?: boolean;
33
+ createdAt?: Date;
34
+ updatedAt?: Date;
35
+ }): Achievement;
36
+ getAchievementId(): string;
37
+ getType(): AchievementType;
38
+ getScope(): AchievementScope;
39
+ getTitle(): string;
40
+ getDescription(): string;
41
+ getTranslations(): AchievementTranslations;
42
+ getTranslation(language: string): AchievementTranslation | undefined;
43
+ getIcon(): string;
44
+ getAlgorithm(): string;
45
+ getIsActive(): boolean;
46
+ getCreatedAt(): Date;
47
+ getUpdatedAt(): Date;
48
+ setTitle(title: string): void;
49
+ setDescription(description: string): void;
50
+ setTranslations(translations: AchievementTranslations): void;
51
+ addTranslation(language: string, translation: AchievementTranslation): void;
52
+ removeTranslation(language: string): void;
53
+ setIcon(icon: string): void;
54
+ setAlgorithm(algorithm: string): void;
55
+ setIsActive(isActive: boolean): void;
56
+ /**
57
+ * Получить локализованное название
58
+ */
59
+ getLocalizedTitle(language: string): string;
60
+ /**
61
+ * Получить локализованное описание
62
+ */
63
+ getLocalizedDescription(language: string): string;
64
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Achievement = void 0;
4
+ class Achievement {
5
+ constructor(achievementId, type, scope, title, description, translations, icon, algorithm, isActive, createdAt, updatedAt) {
6
+ this.achievementId = achievementId;
7
+ this.type = type;
8
+ this.scope = scope;
9
+ this.title = title;
10
+ this.description = description;
11
+ this.translations = translations;
12
+ this.icon = icon;
13
+ this.algorithm = algorithm;
14
+ this.isActive = isActive;
15
+ this.createdAt = createdAt;
16
+ this.updatedAt = updatedAt;
17
+ }
18
+ static create(params) {
19
+ if (!params.achievementId) {
20
+ throw new Error("Achievement creation failed: achievementId is required");
21
+ }
22
+ if (!params.type || (params.type !== "team" && params.type !== "personal")) {
23
+ throw new Error("Achievement creation failed: type must be 'team' or 'personal'");
24
+ }
25
+ if (!params.scope || !["event", "season", "lifetime"].includes(params.scope)) {
26
+ throw new Error("Achievement creation failed: scope must be 'event', 'season', or 'lifetime'");
27
+ }
28
+ if (!params.title) {
29
+ throw new Error("Achievement creation failed: title is required");
30
+ }
31
+ if (!params.description) {
32
+ throw new Error("Achievement creation failed: description is required");
33
+ }
34
+ if (!params.icon) {
35
+ throw new Error("Achievement creation failed: icon is required");
36
+ }
37
+ if (!params.algorithm) {
38
+ throw new Error("Achievement creation failed: algorithm is required");
39
+ }
40
+ const now = new Date();
41
+ return new Achievement(params.achievementId, params.type, params.scope, params.title, params.description, params.translations ?? {}, params.icon, params.algorithm, params.isActive ?? true, params.createdAt ?? now, params.updatedAt ?? now);
42
+ }
43
+ // ---- GETTERS
44
+ getAchievementId() {
45
+ return this.achievementId;
46
+ }
47
+ getType() {
48
+ return this.type;
49
+ }
50
+ getScope() {
51
+ return this.scope;
52
+ }
53
+ getTitle() {
54
+ return this.title;
55
+ }
56
+ getDescription() {
57
+ return this.description;
58
+ }
59
+ getTranslations() {
60
+ return { ...this.translations };
61
+ }
62
+ getTranslation(language) {
63
+ return this.translations[language];
64
+ }
65
+ getIcon() {
66
+ return this.icon;
67
+ }
68
+ getAlgorithm() {
69
+ return this.algorithm;
70
+ }
71
+ getIsActive() {
72
+ return this.isActive;
73
+ }
74
+ getCreatedAt() {
75
+ return this.createdAt;
76
+ }
77
+ getUpdatedAt() {
78
+ return this.updatedAt;
79
+ }
80
+ // ---- SETTERS
81
+ setTitle(title) {
82
+ if (!title) {
83
+ throw new Error("title cannot be empty");
84
+ }
85
+ this.title = title;
86
+ this.updatedAt = new Date();
87
+ }
88
+ setDescription(description) {
89
+ if (!description) {
90
+ throw new Error("description cannot be empty");
91
+ }
92
+ this.description = description;
93
+ this.updatedAt = new Date();
94
+ }
95
+ setTranslations(translations) {
96
+ this.translations = { ...translations };
97
+ this.updatedAt = new Date();
98
+ }
99
+ addTranslation(language, translation) {
100
+ if (!language) {
101
+ throw new Error("language cannot be empty");
102
+ }
103
+ if (!translation.title || !translation.description) {
104
+ throw new Error("translation must have both title and description");
105
+ }
106
+ this.translations[language] = { ...translation };
107
+ this.updatedAt = new Date();
108
+ }
109
+ removeTranslation(language) {
110
+ delete this.translations[language];
111
+ this.updatedAt = new Date();
112
+ }
113
+ setIcon(icon) {
114
+ if (!icon) {
115
+ throw new Error("icon cannot be empty");
116
+ }
117
+ this.icon = icon;
118
+ this.updatedAt = new Date();
119
+ }
120
+ setAlgorithm(algorithm) {
121
+ if (!algorithm) {
122
+ throw new Error("algorithm cannot be empty");
123
+ }
124
+ this.algorithm = algorithm;
125
+ this.updatedAt = new Date();
126
+ }
127
+ setIsActive(isActive) {
128
+ this.isActive = isActive;
129
+ this.updatedAt = new Date();
130
+ }
131
+ /**
132
+ * Получить локализованное название
133
+ */
134
+ getLocalizedTitle(language) {
135
+ const translation = this.getTranslation(language);
136
+ return translation?.title ?? this.title;
137
+ }
138
+ /**
139
+ * Получить локализованное описание
140
+ */
141
+ getLocalizedDescription(language) {
142
+ const translation = this.getTranslation(language);
143
+ return translation?.description ?? this.description;
144
+ }
145
+ }
146
+ exports.Achievement = Achievement;
@@ -4,3 +4,4 @@ export * from "./event";
4
4
  export * from "./event-template";
5
5
  export * from "./stat-group";
6
6
  export * from "./season";
7
+ export * from "./achievement";
@@ -20,3 +20,4 @@ __exportStar(require("./event"), exports);
20
20
  __exportStar(require("./event-template"), exports);
21
21
  __exportStar(require("./stat-group"), exports);
22
22
  __exportStar(require("./season"), exports);
23
+ __exportStar(require("./achievement"), exports);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  export * from "./types";
2
2
  export * from "./utils";
3
- export * from "./domain";
3
+ export { Achievement, AchievementScope, AchievementTranslation, AchievementTranslations } from "./domain/achievement";
4
+ export * from "./domain/user";
5
+ export * from "./domain/group";
6
+ export * from "./domain/event";
7
+ export * from "./domain/event-template";
8
+ export * from "./domain/stat-group";
9
+ export * from "./domain/season";
4
10
  export * from "./ports";
5
11
  export * from "./mongo";
6
12
  export * from "./repositories";
package/dist/index.js CHANGED
@@ -14,9 +14,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Achievement = void 0;
17
18
  __exportStar(require("./types"), exports);
18
19
  __exportStar(require("./utils"), exports);
19
- __exportStar(require("./domain"), exports);
20
+ var achievement_1 = require("./domain/achievement");
21
+ Object.defineProperty(exports, "Achievement", { enumerable: true, get: function () { return achievement_1.Achievement; } });
22
+ __exportStar(require("./domain/user"), exports);
23
+ __exportStar(require("./domain/group"), exports);
24
+ __exportStar(require("./domain/event"), exports);
25
+ __exportStar(require("./domain/event-template"), exports);
26
+ __exportStar(require("./domain/stat-group"), exports);
27
+ __exportStar(require("./domain/season"), exports);
20
28
  __exportStar(require("./ports"), exports);
21
29
  __exportStar(require("./mongo"), exports);
22
30
  __exportStar(require("./repositories"), exports);
@@ -11,3 +11,4 @@ export * from "./schemas/stat-user-profile.schema";
11
11
  export * from "./schemas/stat-user-match-history.schema";
12
12
  export * from "./schemas/stat-event.schema";
13
13
  export * from "./schemas/season.schema";
14
+ export * from "./schemas/achievement.schema";
@@ -27,3 +27,4 @@ __exportStar(require("./schemas/stat-user-profile.schema"), exports);
27
27
  __exportStar(require("./schemas/stat-user-match-history.schema"), exports);
28
28
  __exportStar(require("./schemas/stat-event.schema"), exports);
29
29
  __exportStar(require("./schemas/season.schema"), exports);
30
+ __exportStar(require("./schemas/achievement.schema"), exports);
@@ -0,0 +1,21 @@
1
+ import { Schema } from "mongoose";
2
+ import { AchievementType } from "../../types";
3
+ import { AchievementScope, AchievementTranslations } from "../../domain/achievement";
4
+ export interface AchievementDoc {
5
+ _id: string;
6
+ type: AchievementType;
7
+ scope: AchievementScope;
8
+ title: string;
9
+ description: string;
10
+ translations: AchievementTranslations;
11
+ icon: string;
12
+ algorithm: string;
13
+ isActive: boolean;
14
+ createdAt: Date;
15
+ updatedAt: Date;
16
+ }
17
+ export declare function createAchievementSchema(): Schema<AchievementDoc, import("mongoose").Model<AchievementDoc, any, any, any, import("mongoose").Document<unknown, any, AchievementDoc> & AchievementDoc & Required<{
18
+ _id: string;
19
+ }>, any>, {}, {}, {}, {}, import("mongoose").DefaultSchemaOptions, AchievementDoc, import("mongoose").Document<unknown, {}, import("mongoose").FlatRecord<AchievementDoc>> & import("mongoose").FlatRecord<AchievementDoc> & Required<{
20
+ _id: string;
21
+ }>>;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAchievementSchema = createAchievementSchema;
4
+ const mongoose_1 = require("mongoose");
5
+ function createAchievementSchema() {
6
+ const schema = new mongoose_1.Schema({
7
+ _id: {
8
+ type: String,
9
+ required: true,
10
+ },
11
+ type: {
12
+ type: String,
13
+ enum: ["team", "personal"],
14
+ required: true,
15
+ index: true,
16
+ },
17
+ scope: {
18
+ type: String,
19
+ enum: ["event", "season", "lifetime"],
20
+ required: true,
21
+ index: true,
22
+ },
23
+ title: {
24
+ type: String,
25
+ required: true,
26
+ },
27
+ description: {
28
+ type: String,
29
+ required: true,
30
+ },
31
+ translations: {
32
+ type: mongoose_1.Schema.Types.Mixed,
33
+ required: false,
34
+ default: {},
35
+ },
36
+ icon: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ algorithm: {
41
+ type: String,
42
+ required: true,
43
+ },
44
+ isActive: {
45
+ type: Boolean,
46
+ required: true,
47
+ default: true,
48
+ index: true,
49
+ },
50
+ createdAt: {
51
+ type: Date,
52
+ default: Date.now,
53
+ },
54
+ updatedAt: {
55
+ type: Date,
56
+ default: Date.now,
57
+ },
58
+ }, {
59
+ collection: "achievements",
60
+ timestamps: true,
61
+ });
62
+ // Compound indexes для оптимизации запросов
63
+ schema.index({ type: 1, isActive: 1 }); // Для поиска активных достижений по типу
64
+ schema.index({ scope: 1, isActive: 1 }); // Для поиска активных достижений по scope
65
+ schema.index({ type: 1, scope: 1, isActive: 1 }); // Комбинированный индекс
66
+ return schema;
67
+ }
@@ -0,0 +1,45 @@
1
+ import { Achievement } from "../domain/achievement";
2
+ import { AchievementType } from "../types";
3
+ import { AchievementScope } from "../domain/achievement";
4
+ export interface AchievementsRepository {
5
+ /**
6
+ * Получить достижение по ID
7
+ */
8
+ findById(achievementId: string): Promise<Achievement | null>;
9
+ /**
10
+ * Получить все достижения
11
+ */
12
+ findAll(): Promise<Achievement[]>;
13
+ /**
14
+ * Получить активные достижения
15
+ */
16
+ findActive(): Promise<Achievement[]>;
17
+ /**
18
+ * Получить достижения по типу
19
+ */
20
+ findByType(type: AchievementType, activeOnly?: boolean): Promise<Achievement[]>;
21
+ /**
22
+ * Получить достижения по scope
23
+ */
24
+ findByScope(scope: AchievementScope, activeOnly?: boolean): Promise<Achievement[]>;
25
+ /**
26
+ * Получить достижения по типу и scope
27
+ */
28
+ findByTypeAndScope(type: AchievementType, scope: AchievementScope, activeOnly?: boolean): Promise<Achievement[]>;
29
+ /**
30
+ * Создать новое достижение
31
+ */
32
+ create(achievement: Achievement): Promise<Achievement>;
33
+ /**
34
+ * Обновить достижение
35
+ */
36
+ update(achievement: Achievement): Promise<Achievement | null>;
37
+ /**
38
+ * Удалить достижение
39
+ */
40
+ delete(achievementId: string): Promise<void>;
41
+ /**
42
+ * Проверить существование достижения
43
+ */
44
+ exists(achievementId: string): Promise<boolean>;
45
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -11,3 +11,4 @@ export * from "./stat-user-profile.repository";
11
11
  export * from "./stat-user-match-history.repository";
12
12
  export * from "./stat-event.repository";
13
13
  export * from "./seasons.repository";
14
+ export * from "./achievements.repository";
@@ -27,3 +27,4 @@ __exportStar(require("./stat-user-profile.repository"), exports);
27
27
  __exportStar(require("./stat-user-match-history.repository"), exports);
28
28
  __exportStar(require("./stat-event.repository"), exports);
29
29
  __exportStar(require("./seasons.repository"), exports);
30
+ __exportStar(require("./achievements.repository"), exports);
@@ -11,3 +11,4 @@ export * from "./mongo/stat-user-profile.repository";
11
11
  export * from "./mongo/stat-user-match-history.repository";
12
12
  export * from "./mongo/stat-event.repository";
13
13
  export * from "./mongo/season.repository";
14
+ export * from "./mongo/achievement.repository";
@@ -27,3 +27,4 @@ __exportStar(require("./mongo/stat-user-profile.repository"), exports);
27
27
  __exportStar(require("./mongo/stat-user-match-history.repository"), exports);
28
28
  __exportStar(require("./mongo/stat-event.repository"), exports);
29
29
  __exportStar(require("./mongo/season.repository"), exports);
30
+ __exportStar(require("./mongo/achievement.repository"), exports);
@@ -0,0 +1,4 @@
1
+ import { Achievement } from "../../domain/achievement";
2
+ import { AchievementDoc } from "../../mongo";
3
+ export declare function toDomain(doc: AchievementDoc): Achievement;
4
+ export declare function toDoc(achievement: Achievement): AchievementDoc;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toDomain = toDomain;
4
+ exports.toDoc = toDoc;
5
+ const achievement_1 = require("../../domain/achievement");
6
+ function toDomain(doc) {
7
+ return achievement_1.Achievement.create({
8
+ achievementId: doc._id,
9
+ type: doc.type,
10
+ scope: doc.scope,
11
+ title: doc.title,
12
+ description: doc.description,
13
+ translations: doc.translations,
14
+ icon: doc.icon,
15
+ algorithm: doc.algorithm,
16
+ isActive: doc.isActive,
17
+ createdAt: doc.createdAt,
18
+ updatedAt: doc.updatedAt,
19
+ });
20
+ }
21
+ function toDoc(achievement) {
22
+ return {
23
+ _id: achievement.getAchievementId(),
24
+ type: achievement.getType(),
25
+ scope: achievement.getScope(),
26
+ title: achievement.getTitle(),
27
+ description: achievement.getDescription(),
28
+ translations: achievement.getTranslations(),
29
+ icon: achievement.getIcon(),
30
+ algorithm: achievement.getAlgorithm(),
31
+ isActive: achievement.getIsActive(),
32
+ createdAt: achievement.getCreatedAt(),
33
+ updatedAt: achievement.getUpdatedAt(),
34
+ };
35
+ }
@@ -0,0 +1,20 @@
1
+ import type { Model } from "mongoose";
2
+ import type { AchievementsRepository } from "../../ports/achievements.repository";
3
+ import type { AchievementDoc } from "../../mongo";
4
+ import { Achievement } from "../../domain/achievement";
5
+ import { AchievementType } from "../../types";
6
+ import { AchievementScope } from "../../domain/achievement";
7
+ export declare class MongoAchievementsRepository implements AchievementsRepository {
8
+ private readonly AchievementModel;
9
+ constructor(AchievementModel: Model<AchievementDoc>);
10
+ findById(achievementId: string): Promise<Achievement | null>;
11
+ findAll(): Promise<Achievement[]>;
12
+ findActive(): Promise<Achievement[]>;
13
+ findByType(type: AchievementType, activeOnly?: boolean): Promise<Achievement[]>;
14
+ findByScope(scope: AchievementScope, activeOnly?: boolean): Promise<Achievement[]>;
15
+ findByTypeAndScope(type: AchievementType, scope: AchievementScope, activeOnly?: boolean): Promise<Achievement[]>;
16
+ create(achievement: Achievement): Promise<Achievement>;
17
+ update(achievement: Achievement): Promise<Achievement | null>;
18
+ delete(achievementId: string): Promise<void>;
19
+ exists(achievementId: string): Promise<boolean>;
20
+ }
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoAchievementsRepository = void 0;
4
+ const achievement_mapper_1 = require("./achievement.mapper");
5
+ const errors_1 = require("../../errors");
6
+ class MongoAchievementsRepository {
7
+ constructor(AchievementModel) {
8
+ this.AchievementModel = AchievementModel;
9
+ }
10
+ async findById(achievementId) {
11
+ try {
12
+ if (!achievementId) {
13
+ throw new errors_1.ValidationError("Achievement", "achievementId", achievementId, "achievementId is required");
14
+ }
15
+ const doc = await this.AchievementModel.findById(achievementId).lean();
16
+ return doc ? (0, achievement_mapper_1.toDomain)(doc) : null;
17
+ }
18
+ catch (error) {
19
+ if (error instanceof errors_1.ValidationError) {
20
+ throw error;
21
+ }
22
+ throw new errors_1.QueryError("findById", "Achievement", achievementId, error);
23
+ }
24
+ }
25
+ async findAll() {
26
+ try {
27
+ const docs = await this.AchievementModel.find().lean();
28
+ return docs.map((doc) => (0, achievement_mapper_1.toDomain)(doc));
29
+ }
30
+ catch (error) {
31
+ throw new errors_1.QueryError("findAll", "Achievement", "all", error);
32
+ }
33
+ }
34
+ async findActive() {
35
+ try {
36
+ const docs = await this.AchievementModel.find({ isActive: true }).lean();
37
+ return docs.map((doc) => (0, achievement_mapper_1.toDomain)(doc));
38
+ }
39
+ catch (error) {
40
+ throw new errors_1.QueryError("findActive", "Achievement", "active", error);
41
+ }
42
+ }
43
+ async findByType(type, activeOnly = false) {
44
+ try {
45
+ if (!type || (type !== "team" && type !== "personal")) {
46
+ throw new errors_1.ValidationError("Achievement", "type", type, "type must be 'team' or 'personal'");
47
+ }
48
+ const query = { type };
49
+ if (activeOnly) {
50
+ query.isActive = true;
51
+ }
52
+ const docs = await this.AchievementModel.find(query).lean();
53
+ return docs.map((doc) => (0, achievement_mapper_1.toDomain)(doc));
54
+ }
55
+ catch (error) {
56
+ if (error instanceof errors_1.ValidationError) {
57
+ throw error;
58
+ }
59
+ throw new errors_1.QueryError("findByType", "Achievement", type, error);
60
+ }
61
+ }
62
+ async findByScope(scope, activeOnly = false) {
63
+ try {
64
+ if (!scope || !["event", "season", "lifetime"].includes(scope)) {
65
+ throw new errors_1.ValidationError("Achievement", "scope", scope, "scope must be 'event', 'season', or 'lifetime'");
66
+ }
67
+ const query = { scope };
68
+ if (activeOnly) {
69
+ query.isActive = true;
70
+ }
71
+ const docs = await this.AchievementModel.find(query).lean();
72
+ return docs.map((doc) => (0, achievement_mapper_1.toDomain)(doc));
73
+ }
74
+ catch (error) {
75
+ if (error instanceof errors_1.ValidationError) {
76
+ throw error;
77
+ }
78
+ throw new errors_1.QueryError("findByScope", "Achievement", scope, error);
79
+ }
80
+ }
81
+ async findByTypeAndScope(type, scope, activeOnly = false) {
82
+ try {
83
+ if (!type || (type !== "team" && type !== "personal")) {
84
+ throw new errors_1.ValidationError("Achievement", "type", type, "type must be 'team' or 'personal'");
85
+ }
86
+ if (!scope || !["event", "season", "lifetime"].includes(scope)) {
87
+ throw new errors_1.ValidationError("Achievement", "scope", scope, "scope must be 'event', 'season', or 'lifetime'");
88
+ }
89
+ const query = { type, scope };
90
+ if (activeOnly) {
91
+ query.isActive = true;
92
+ }
93
+ const docs = await this.AchievementModel.find(query).lean();
94
+ return docs.map((doc) => (0, achievement_mapper_1.toDomain)(doc));
95
+ }
96
+ catch (error) {
97
+ if (error instanceof errors_1.ValidationError) {
98
+ throw error;
99
+ }
100
+ throw new errors_1.QueryError("findByTypeAndScope", "Achievement", `${type}-${scope}`, error);
101
+ }
102
+ }
103
+ async create(achievement) {
104
+ try {
105
+ if (!achievement) {
106
+ throw new errors_1.ValidationError("Achievement", "achievement", achievement, "achievement object is required");
107
+ }
108
+ const achievementId = achievement.getAchievementId();
109
+ if (!achievementId) {
110
+ throw new errors_1.ValidationError("Achievement", "achievementId", achievementId, "achievementId is required");
111
+ }
112
+ const write = (0, achievement_mapper_1.toDoc)(achievement);
113
+ const saved = await new this.AchievementModel(write).save();
114
+ return (0, achievement_mapper_1.toDomain)(saved.toObject());
115
+ }
116
+ catch (error) {
117
+ if (error instanceof errors_1.ValidationError) {
118
+ throw error;
119
+ }
120
+ // Check for duplicate key error
121
+ if (error?.code === 11000) {
122
+ throw new errors_1.DuplicateEntityError("Achievement", achievement.getAchievementId(), error);
123
+ }
124
+ throw new errors_1.QueryError("create", "Achievement", achievement.getAchievementId(), error);
125
+ }
126
+ }
127
+ async update(achievement) {
128
+ try {
129
+ if (!achievement) {
130
+ throw new errors_1.ValidationError("Achievement", "achievement", achievement, "achievement object is required");
131
+ }
132
+ const achievementId = achievement.getAchievementId();
133
+ if (!achievementId) {
134
+ throw new errors_1.ValidationError("Achievement", "achievementId", achievementId, "achievementId is required");
135
+ }
136
+ const write = (0, achievement_mapper_1.toDoc)(achievement);
137
+ const doc = await this.AchievementModel.findByIdAndUpdate(achievementId, { $set: write }, { new: true }).lean();
138
+ return doc ? (0, achievement_mapper_1.toDomain)(doc) : null;
139
+ }
140
+ catch (error) {
141
+ if (error instanceof errors_1.ValidationError) {
142
+ throw error;
143
+ }
144
+ throw new errors_1.QueryError("update", "Achievement", achievement.getAchievementId(), error);
145
+ }
146
+ }
147
+ async delete(achievementId) {
148
+ try {
149
+ if (!achievementId) {
150
+ throw new errors_1.ValidationError("Achievement", "achievementId", achievementId, "achievementId is required");
151
+ }
152
+ const result = await this.AchievementModel.findByIdAndDelete(achievementId);
153
+ if (!result) {
154
+ throw new errors_1.EntityNotFoundError("Achievement", achievementId, "delete");
155
+ }
156
+ }
157
+ catch (error) {
158
+ if (error instanceof errors_1.ValidationError || error instanceof errors_1.EntityNotFoundError) {
159
+ throw error;
160
+ }
161
+ throw new errors_1.QueryError("delete", "Achievement", achievementId, error);
162
+ }
163
+ }
164
+ async exists(achievementId) {
165
+ try {
166
+ if (!achievementId) {
167
+ throw new errors_1.ValidationError("Achievement", "achievementId", achievementId, "achievementId is required");
168
+ }
169
+ const count = await this.AchievementModel.countDocuments({ _id: achievementId });
170
+ return count > 0;
171
+ }
172
+ catch (error) {
173
+ if (error instanceof errors_1.ValidationError) {
174
+ throw error;
175
+ }
176
+ throw new errors_1.QueryError("exists", "Achievement", achievementId, error);
177
+ }
178
+ }
179
+ }
180
+ exports.MongoAchievementsRepository = MongoAchievementsRepository;
@@ -36,9 +36,7 @@ class MongoSeasonsRepository {
36
36
  throw new errors_1.ValidationError('Season', 'groupId', groupId, 'must be a non-zero number');
37
37
  }
38
38
  const docs = await this.Model.find({
39
- $or: [
40
- { groupId: groupId }
41
- ]
39
+ groupId: groupId
42
40
  }).sort({ year: -1, startDate: -1 }).lean();
43
41
  return docs.map(d => (0, season_mapper_1.toDomain)(d));
44
42
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ballrush-core",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/jest": "^30.0.0",
31
+ "baseline-browser-mapping": "^2.8.30",
31
32
  "jest": "^30.1.3",
32
33
  "mongoose": "^7.8.7",
33
34
  "rimraf": "^5.0.0",