crazy-odds-bet-shared 1.0.1 → 1.0.3
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/models/base.js +2 -50
- package/models/bookmaker.js +6 -2
- package/models/competition.js +3 -7
- package/models/fixture.js +0 -4
- package/models/player.js +1 -2
- package/models/sport.js +2 -6
- package/models/team.js +1 -2
- package/package.json +1 -1
- package/utils/index.js +2 -1
- package/utils/test.js +8 -0
- package/README.md +0 -182
package/models/base.js
CHANGED
|
@@ -53,7 +53,7 @@ const generateSlug = (text) => {
|
|
|
53
53
|
* @param sourceField The field to generate the slug from (defaults to 'name')
|
|
54
54
|
*/
|
|
55
55
|
const addAutoSlugHook = (schema, sourceField = 'name') => {
|
|
56
|
-
schema.pre('
|
|
56
|
+
schema.pre('validate', function (next) {
|
|
57
57
|
if (this.isModified(sourceField) || !this.get('slug')) {
|
|
58
58
|
const sourceValue = this.get(sourceField);
|
|
59
59
|
if (sourceValue) {
|
|
@@ -64,58 +64,10 @@ const addAutoSlugHook = (schema, sourceField = 'name') => {
|
|
|
64
64
|
});
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
/**
|
|
68
|
-
* Adds slug generation for external reference arrays on save
|
|
69
|
-
* @param schema The mongoose schema to add the hook to
|
|
70
|
-
* @param refPath The path to the external refs array (defaults to 'externalRefs')
|
|
71
|
-
* @param sourceField The field to generate the slug from inside each ref (defaults to 'name')
|
|
72
|
-
*/
|
|
73
|
-
const addExternalRefsSlugHook = (
|
|
74
|
-
schema,
|
|
75
|
-
refPath = 'externalRefs',
|
|
76
|
-
sourceField = 'name'
|
|
77
|
-
) => {
|
|
78
|
-
schema.pre('save', function (next) {
|
|
79
|
-
const refs = this.get(refPath);
|
|
80
|
-
if (Array.isArray(refs)) {
|
|
81
|
-
const updated = refs.map((ref) => {
|
|
82
|
-
if (ref && !ref.slug && ref[sourceField]) {
|
|
83
|
-
return { ...ref, slug: generateSlug(ref[sourceField]) };
|
|
84
|
-
}
|
|
85
|
-
return ref;
|
|
86
|
-
});
|
|
87
|
-
this.set(refPath, updated);
|
|
88
|
-
} else if (refs && typeof refs === 'object') {
|
|
89
|
-
if (refs instanceof Map) {
|
|
90
|
-
const updated = new Map(refs);
|
|
91
|
-
updated.forEach((ref, key) => {
|
|
92
|
-
if (ref && !ref.slug && ref[sourceField]) {
|
|
93
|
-
updated.set(key, { ...ref, slug: generateSlug(ref[sourceField]) });
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
this.set(refPath, updated);
|
|
97
|
-
} else {
|
|
98
|
-
const updated = {};
|
|
99
|
-
for (const key of Object.keys(refs)) {
|
|
100
|
-
const ref = refs[key];
|
|
101
|
-
if (ref && !ref.slug && ref[sourceField]) {
|
|
102
|
-
updated[key] = { ...ref, slug: generateSlug(ref[sourceField]) };
|
|
103
|
-
} else {
|
|
104
|
-
updated[key] = ref;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
this.set(refPath, updated);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
next();
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
|
-
|
|
114
67
|
module.exports = {
|
|
115
68
|
externalRefSchema,
|
|
116
69
|
baseSchemaOptions,
|
|
117
70
|
createBaseSchema,
|
|
118
71
|
generateSlug,
|
|
119
|
-
addAutoSlugHook
|
|
120
|
-
addExternalRefsSlugHook
|
|
72
|
+
addAutoSlugHook
|
|
121
73
|
};
|
package/models/bookmaker.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
const { Schema, model } = require('mongoose');
|
|
2
|
-
const {
|
|
2
|
+
const {
|
|
3
|
+
createBaseSchema,
|
|
4
|
+
baseSchemaOptions,
|
|
5
|
+
addAutoSlugHook
|
|
6
|
+
} = require('./base');
|
|
3
7
|
|
|
4
8
|
const bookmakerSchema = new Schema(
|
|
5
9
|
{
|
|
6
10
|
...createBaseSchema(),
|
|
7
11
|
name: { type: String, required: true },
|
|
8
|
-
slug: { type: String,
|
|
12
|
+
slug: { type: String, unique: true, sparse: true },
|
|
9
13
|
country: { type: String, required: false, sparse: true },
|
|
10
14
|
website: { type: String, required: false, sparse: true },
|
|
11
15
|
isActive: { type: Boolean, default: true },
|
package/models/competition.js
CHANGED
|
@@ -2,8 +2,7 @@ const { Schema, model } = require('mongoose');
|
|
|
2
2
|
const {
|
|
3
3
|
createBaseSchema,
|
|
4
4
|
baseSchemaOptions,
|
|
5
|
-
addAutoSlugHook
|
|
6
|
-
addExternalRefsSlugHook
|
|
5
|
+
addAutoSlugHook
|
|
7
6
|
} = require('./base');
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -14,7 +13,7 @@ const competitionSchema = new Schema(
|
|
|
14
13
|
...createBaseSchema(),
|
|
15
14
|
sportId: { type: String, required: true, ref: 'Sport' },
|
|
16
15
|
name: { type: String, required: true },
|
|
17
|
-
slug: { type: String,
|
|
16
|
+
slug: { type: String, unique: true, sparse: true },
|
|
18
17
|
country: { type: String, required: false, sparse: true },
|
|
19
18
|
season: { type: String, required: false, sparse: true },
|
|
20
19
|
isActive: { type: Boolean, default: true },
|
|
@@ -27,7 +26,7 @@ const competitionSchema = new Schema(
|
|
|
27
26
|
);
|
|
28
27
|
|
|
29
28
|
// Indexes
|
|
30
|
-
competitionSchema.index({ slug: 1,
|
|
29
|
+
competitionSchema.index({ slug: 1, sportId: 1 }, { unique: true, sparse: true });
|
|
31
30
|
competitionSchema.index({ sportId: 1 });
|
|
32
31
|
competitionSchema.index({ isActive: 1 });
|
|
33
32
|
competitionSchema.index({ name: 'text' });
|
|
@@ -68,9 +67,6 @@ competitionSchema.pre('save', function (next) {
|
|
|
68
67
|
// Add auto-slug generation from name field
|
|
69
68
|
addAutoSlugHook(competitionSchema, 'name');
|
|
70
69
|
|
|
71
|
-
// Add auto-slug generation for external refs
|
|
72
|
-
addExternalRefsSlugHook(competitionSchema, 'externalRefs');
|
|
73
|
-
|
|
74
70
|
// Static methods
|
|
75
71
|
competitionSchema.static('findBySlug', function (slug, sport, season) {
|
|
76
72
|
const query = { slug };
|
package/models/fixture.js
CHANGED
|
@@ -2,7 +2,6 @@ const { Schema, model } = require('mongoose');
|
|
|
2
2
|
const {
|
|
3
3
|
createBaseSchema,
|
|
4
4
|
baseSchemaOptions,
|
|
5
|
-
addExternalRefsSlugHook
|
|
6
5
|
} = require('./base');
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -50,9 +49,6 @@ fixtureSchema.index({ scheduledAt: 1 });
|
|
|
50
49
|
fixtureSchema.index({ status: 1 });
|
|
51
50
|
fixtureSchema.index({ scheduledAt: 1, status: 1 });
|
|
52
51
|
|
|
53
|
-
// Add auto-slug generation for external refs
|
|
54
|
-
addExternalRefsSlugHook(fixtureSchema, 'externalRefs');
|
|
55
|
-
|
|
56
52
|
// Virtuals
|
|
57
53
|
fixtureSchema.virtual('sport', {
|
|
58
54
|
ref: 'Sport',
|
package/models/player.js
CHANGED
package/models/sport.js
CHANGED
|
@@ -2,8 +2,7 @@ const { Schema, model } = require('mongoose');
|
|
|
2
2
|
const {
|
|
3
3
|
createBaseSchema,
|
|
4
4
|
baseSchemaOptions,
|
|
5
|
-
addAutoSlugHook
|
|
6
|
-
addExternalRefsSlugHook
|
|
5
|
+
addAutoSlugHook
|
|
7
6
|
} = require('./base');
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -13,7 +12,7 @@ const sportSchema = new Schema(
|
|
|
13
12
|
{
|
|
14
13
|
...createBaseSchema(),
|
|
15
14
|
name: { type: String, required: true },
|
|
16
|
-
slug: { type: String,
|
|
15
|
+
slug: { type: String, unique: true, sparse: true },
|
|
17
16
|
displayName: { type: String, required: true },
|
|
18
17
|
isActive: { type: Boolean, default: true },
|
|
19
18
|
externalRefs: { type: Schema.Types.Mixed, default: {} }
|
|
@@ -57,9 +56,6 @@ sportSchema.pre('save', function (next) {
|
|
|
57
56
|
// Add auto-slug generation from name field
|
|
58
57
|
addAutoSlugHook(sportSchema, 'name');
|
|
59
58
|
|
|
60
|
-
// Add auto-slug generation for external refs
|
|
61
|
-
addExternalRefsSlugHook(sportSchema, 'externalRefs');
|
|
62
|
-
|
|
63
59
|
// Static methods
|
|
64
60
|
sportSchema.static('findBySlug', function (slug) {
|
|
65
61
|
return this.findOne({ slug });
|
package/models/team.js
CHANGED
package/package.json
CHANGED
package/utils/index.js
CHANGED
package/utils/test.js
ADDED
package/README.md
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
# Shared
|
|
2
|
-
|
|
3
|
-
Shared MongoDB models and database utilities for the odds project.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **MongoDB Connection Manager**: Easy connect/disconnect functionality
|
|
8
|
-
- **Mongoose Models**: Pre-built models with TypeScript support
|
|
9
|
-
- Bookmakers
|
|
10
|
-
- Sports
|
|
11
|
-
- Competitions
|
|
12
|
-
- Teams
|
|
13
|
-
- Fixtures
|
|
14
|
-
- **Common Schema Utilities**: UUID-based IDs, timestamps, external references
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
cd shared
|
|
20
|
-
npm install
|
|
21
|
-
npm run build
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Configuration
|
|
25
|
-
|
|
26
|
-
Copy `.env.example` to `.env` and configure your MongoDB connection. The shared
|
|
27
|
-
package loads its own `.env` file and overrides other envs, so the API and
|
|
28
|
-
collector both use these settings.
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
cp .env.example .env
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Edit `.env` (Atlas SRV example):
|
|
35
|
-
|
|
36
|
-
```env
|
|
37
|
-
MONGODB_URI=mongodb+srv://username:password@cluster0.gmu25o7.mongodb.net/?retryWrites=true&w=majority
|
|
38
|
-
DB_NAME=odds_dev
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Local MongoDB example:
|
|
42
|
-
|
|
43
|
-
```env
|
|
44
|
-
MONGODB_URI=mongodb://127.0.0.1:27017
|
|
45
|
-
DB_NAME=odds_project
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
DNS note (Windows): If SRV resolution fails, verify your cluster host resolves:
|
|
49
|
-
|
|
50
|
-
```powershell
|
|
51
|
-
nslookup _mongodb._tcp.<your-cluster>.mongodb.net
|
|
52
|
-
nslookup <your-cluster>.mongodb.net
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Usage
|
|
56
|
-
|
|
57
|
-
### Connecting to MongoDB
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { MongoDB } from "@odds-project/shared/db";
|
|
61
|
-
|
|
62
|
-
// Connect using environment variables (from shared/.env)
|
|
63
|
-
await MongoDB.connect();
|
|
64
|
-
|
|
65
|
-
// Or provide connection details explicitly
|
|
66
|
-
await MongoDB.connect("mongodb://localhost:27017", "odds_db");
|
|
67
|
-
|
|
68
|
-
// Check connection
|
|
69
|
-
if (MongoDB.isConnected()) {
|
|
70
|
-
console.log("Connected!");
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Disconnect
|
|
74
|
-
await MongoDB.disconnect();
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Using Models
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
import {
|
|
81
|
-
Bookmaker,
|
|
82
|
-
Fixture,
|
|
83
|
-
FixtureStatus,
|
|
84
|
-
Sport,
|
|
85
|
-
} from "@odds-project/shared/models";
|
|
86
|
-
|
|
87
|
-
// Create a bookmaker
|
|
88
|
-
const bookmaker = await Bookmaker.create({
|
|
89
|
-
name: "Bet365",
|
|
90
|
-
slug: "bet365",
|
|
91
|
-
country: "UK",
|
|
92
|
-
website: "https://www.bet365.com",
|
|
93
|
-
isActive: true,
|
|
94
|
-
metadata: { rating: 4.5 },
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Create a sport
|
|
98
|
-
const sport = await Sport.create({
|
|
99
|
-
name: "Football",
|
|
100
|
-
slug: "football",
|
|
101
|
-
displayName: "Football",
|
|
102
|
-
isActive: true,
|
|
103
|
-
externalRefs: [
|
|
104
|
-
{
|
|
105
|
-
id: "ext-123",
|
|
106
|
-
name: "Provider A",
|
|
107
|
-
slug: "provider-a",
|
|
108
|
-
isActive: true,
|
|
109
|
-
metadata: {},
|
|
110
|
-
},
|
|
111
|
-
],
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Create a fixture
|
|
115
|
-
const fixture = await Fixture.create({
|
|
116
|
-
sportId: sport._id,
|
|
117
|
-
competitionId: "comp-uuid",
|
|
118
|
-
homeTeamId: "team1-uuid",
|
|
119
|
-
awayTeamId: "team2-uuid",
|
|
120
|
-
scheduledAt: new Date("2025-12-25T15:00:00Z"),
|
|
121
|
-
status: FixtureStatus.SCHEDULED,
|
|
122
|
-
externalRefs: [],
|
|
123
|
-
metadata: { venue: "Stadium Name" },
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Query fixtures
|
|
127
|
-
const upcomingFixtures = await Fixture.find({
|
|
128
|
-
status: FixtureStatus.SCHEDULED,
|
|
129
|
-
scheduledAt: { $gte: new Date() },
|
|
130
|
-
}).sort({ scheduledAt: 1 });
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Models
|
|
134
|
-
|
|
135
|
-
### Bookmaker
|
|
136
|
-
|
|
137
|
-
- name, slug, country, website
|
|
138
|
-
- isActive flag
|
|
139
|
-
- metadata object
|
|
140
|
-
|
|
141
|
-
### Sport
|
|
142
|
-
|
|
143
|
-
- name, slug, displayName
|
|
144
|
-
- isActive flag
|
|
145
|
-
- externalRefs array
|
|
146
|
-
|
|
147
|
-
### Competition
|
|
148
|
-
|
|
149
|
-
- sportId (ref to Sport)
|
|
150
|
-
- name, slug, country, season
|
|
151
|
-
- isActive flag
|
|
152
|
-
- externalRefs array
|
|
153
|
-
|
|
154
|
-
### Team
|
|
155
|
-
|
|
156
|
-
- sportId (ref to Sport)
|
|
157
|
-
- name, slug
|
|
158
|
-
- isActive flag
|
|
159
|
-
- externalRefs array
|
|
160
|
-
|
|
161
|
-
### Fixture
|
|
162
|
-
|
|
163
|
-
- sportId, competitionId, homeTeamId, awayTeamId (refs)
|
|
164
|
-
- scheduledAt (Date)
|
|
165
|
-
- status (scheduled | live | finished | postponed | cancelled)
|
|
166
|
-
- externalRefs array
|
|
167
|
-
- metadata object
|
|
168
|
-
|
|
169
|
-
## Common Features
|
|
170
|
-
|
|
171
|
-
All models include:
|
|
172
|
-
|
|
173
|
-
- `_id`: UUID string (generated automatically)
|
|
174
|
-
- `createdAt`: timestamp
|
|
175
|
-
- `updatedAt`: timestamp
|
|
176
|
-
- No version key (`__v`)
|
|
177
|
-
|
|
178
|
-
## Scripts
|
|
179
|
-
|
|
180
|
-
- `npm run build`: Compile TypeScript to JavaScript
|
|
181
|
-
- `npm run dev`: Watch mode for development
|
|
182
|
-
- `npm run clean`: Remove dist folder
|