@weekendgoals/weekendgoals-common 1.1908.22254273988 → 1.1909.22283215374
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/dist/matching/normalize.d.ts +24 -0
- package/dist/matching/normalize.d.ts.map +1 -0
- package/dist/matching/normalize.js +198 -0
- package/dist/matching/normalize.js.map +1 -0
- package/dist/matching/team-matcher.d.ts +21 -0
- package/dist/matching/team-matcher.d.ts.map +1 -0
- package/dist/matching/team-matcher.js +44 -0
- package/dist/matching/team-matcher.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Category } from "@weekendgoals/weekendgoals-types/dist/types";
|
|
2
|
+
export declare function normalize(name: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a country name, resolving known aliases to DB canonical names.
|
|
5
|
+
*/
|
|
6
|
+
export declare function normalizeCountry(country: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a team name + country to the DB canonical form.
|
|
9
|
+
* Returns null if no alias exists.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveTeamAlias(normName: string, normCountry: string): {
|
|
12
|
+
name: string;
|
|
13
|
+
country: string;
|
|
14
|
+
} | null;
|
|
15
|
+
export declare function inferCategory(leagueName: string): Category;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a league name + country to the DB canonical form.
|
|
18
|
+
* Returns null if no alias exists.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveLeagueAlias(normName: string, normCountry: string): {
|
|
21
|
+
name: string;
|
|
22
|
+
country: string;
|
|
23
|
+
} | null;
|
|
24
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/matching/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AAEvE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS9C;AAkCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGxD;AA6DD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK1C;AAYD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAI1D;AA8DD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK1C"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalize = normalize;
|
|
4
|
+
exports.normalizeCountry = normalizeCountry;
|
|
5
|
+
exports.resolveTeamAlias = resolveTeamAlias;
|
|
6
|
+
exports.inferCategory = inferCategory;
|
|
7
|
+
exports.resolveLeagueAlias = resolveLeagueAlias;
|
|
8
|
+
function normalize(name) {
|
|
9
|
+
return name
|
|
10
|
+
.normalize("NFD") // decompose accents: "ä" → "a" + combining diaeresis
|
|
11
|
+
.replace(/[\u0300-\u036f]/g, "") // strip combining diacritical marks
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[-_]/g, " ")
|
|
14
|
+
.replace(/[^a-z0-9 ]/g, "")
|
|
15
|
+
.replace(/\s+/g, " ")
|
|
16
|
+
.trim();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Maps alternative country names to the canonical name used in our DB.
|
|
20
|
+
* Keys are normalized (lowercase, stripped of special chars).
|
|
21
|
+
* Both Opta and FIFA use slightly different names than API-Football.
|
|
22
|
+
*/
|
|
23
|
+
const COUNTRY_ALIASES = {
|
|
24
|
+
// Opta uses "Türkiye" → NFD normalize → "turkiye"
|
|
25
|
+
"turkiye": "turkey",
|
|
26
|
+
// Opta/FIFA vs our DB
|
|
27
|
+
"czechia": "czech republic",
|
|
28
|
+
"china pr": "china",
|
|
29
|
+
"korea republic": "south korea",
|
|
30
|
+
"korea dpr": "north korea",
|
|
31
|
+
"republic of ireland": "ireland",
|
|
32
|
+
// "Côte d'Ivoire" → NFD → "cote divoire"
|
|
33
|
+
"cote divoire": "ivory coast",
|
|
34
|
+
"bosnia and herzegovina": "bosnia",
|
|
35
|
+
"cabo verde": "cape verde islands",
|
|
36
|
+
"brunei darussalam": "brunei",
|
|
37
|
+
// "São Tomé e Príncipe" / "São Tomé and Príncipe" → NFD → "sao tome..."
|
|
38
|
+
"sao tome e principe": "sao tome e principe",
|
|
39
|
+
"sao tome and principe": "sao tome e principe",
|
|
40
|
+
// "Réunion" → NFD → "reunion"
|
|
41
|
+
"reunion": "reunion",
|
|
42
|
+
// "Curaçao" → NFD → "curacao"
|
|
43
|
+
"curacao": "curacao",
|
|
44
|
+
// FIFA-specific aliases
|
|
45
|
+
"ir iran": "iran",
|
|
46
|
+
"korea": "south korea",
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Normalize a country name, resolving known aliases to DB canonical names.
|
|
50
|
+
*/
|
|
51
|
+
function normalizeCountry(country) {
|
|
52
|
+
const norm = normalize(country);
|
|
53
|
+
return COUNTRY_ALIASES[norm] || norm;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Maps Opta/FIFA team names to our DB names when they differ significantly.
|
|
57
|
+
* Key: "normalizedOptaName::normalizedCountry"
|
|
58
|
+
* Value: "normalizedDbName::normalizedDbCountry"
|
|
59
|
+
*/
|
|
60
|
+
const TEAM_ALIASES = {
|
|
61
|
+
// Short names / nicknames
|
|
62
|
+
"wolverhampton wanderers::england": "wolves::england",
|
|
63
|
+
"agf::denmark": "aarhus::denmark",
|
|
64
|
+
"ob::denmark": "odense::denmark",
|
|
65
|
+
"az::netherlands": "az alkmaar::netherlands",
|
|
66
|
+
"la galaxy::usa": "los angeles galaxy::usa",
|
|
67
|
+
"sj earthquakes::usa": "san jose earthquakes::usa",
|
|
68
|
+
"lsk::norway": "lillestrom::norway",
|
|
69
|
+
// Different naming conventions
|
|
70
|
+
"queens park rangers::england": "qpr::england",
|
|
71
|
+
"stgallen::switzerland": "fc st gallen::switzerland",
|
|
72
|
+
"dac 1904::slovakia": "dunajska streda::slovakia",
|
|
73
|
+
"rsb berkane::morocco": "renaissance berkane::morocco",
|
|
74
|
+
"wydad casablanca::morocco": "wydad ac::morocco",
|
|
75
|
+
"al qadsiah::saudi arabia": "al qadisiyah fc::saudi arabia",
|
|
76
|
+
"gaziantep fk::turkey": "gazisehir gaziantep::turkey",
|
|
77
|
+
"universidad catolica::chile": "u catolica::chile",
|
|
78
|
+
"aguilas doradas::colombia": "rionegro aguilas::colombia",
|
|
79
|
+
"neftci::azerbaijan": "neftchi baku::azerbaijan",
|
|
80
|
+
"ulsan hd::south korea": "ulsan hyundai fc::south korea",
|
|
81
|
+
"hapoel jerusalem::israel": "hapoel katamon::israel",
|
|
82
|
+
// Country mismatch — Derry City plays in Ireland's league but is in Northern Ireland
|
|
83
|
+
"derry city::northern ireland": "derry city::ireland",
|
|
84
|
+
// Opta uses different names for Lyon teams
|
|
85
|
+
"olympique lyonnais::france": "lyon::france",
|
|
86
|
+
"ol lyonnes::france": "lyon w::france",
|
|
87
|
+
// Opta full names vs DB short names
|
|
88
|
+
"internazionale::italy": "inter::italy",
|
|
89
|
+
"brest::france": "stade brestois 29::france",
|
|
90
|
+
"kbenhavn::denmark": "fc copenhagen::denmark",
|
|
91
|
+
"west bromwich albion::england": "west brom::england",
|
|
92
|
+
// Opta name differs from DB name (men)
|
|
93
|
+
"slaven koprivnica::croatia": "nk slaven belupo::croatia",
|
|
94
|
+
"wsg tirol::austria": "wsg wattens::austria",
|
|
95
|
+
"torpedo belaz::belarus": "torpedo zhodino::belarus",
|
|
96
|
+
"blau wei linz::austria": "fc bw linz::austria",
|
|
97
|
+
"wehen wiesbaden::germany": "sv wehen::germany",
|
|
98
|
+
"etoile du sahel::tunisia": "es sahel::tunisia",
|
|
99
|
+
"monastir::tunisia": "us monastirienne::tunisia",
|
|
100
|
+
"porto ii::portugal": "fc porto b::portugal",
|
|
101
|
+
"city torque::uruguay": "atletico torque::uruguay",
|
|
102
|
+
"atletico huila::colombia": "huila::colombia",
|
|
103
|
+
"nacional::uruguay": "club nacional::uruguay",
|
|
104
|
+
"renaissance zemamra::morocco": "cr khemis zemamra::morocco",
|
|
105
|
+
"erzurumspor fk::turkey": "erzurum bb::turkey",
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Resolve a team name + country to the DB canonical form.
|
|
109
|
+
* Returns null if no alias exists.
|
|
110
|
+
*/
|
|
111
|
+
function resolveTeamAlias(normName, normCountry) {
|
|
112
|
+
const alias = TEAM_ALIASES[`${normName}::${normCountry}`];
|
|
113
|
+
if (!alias)
|
|
114
|
+
return null;
|
|
115
|
+
const sep = alias.indexOf("::");
|
|
116
|
+
return { name: alias.substring(0, sep), country: alias.substring(sep + 2) };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Infer team/league category from a league name.
|
|
120
|
+
* Uses the same patterns as update-league-ranks.ts.
|
|
121
|
+
*/
|
|
122
|
+
const WOMEN_PATTERN = /\bwomen'?s?\b|\bfemenina?\b|\bfemenil\b|\bfrauen|\bf[ée]minin|\bWSL\b|\bLiga F\b|\bkvinde|\bSWPL\b|\bSWF\b|\bWPSL\b|\bNWSL\b|\bWK[- ]?League\b|\bWE League\b|\bElitettan\b|\bUSL W\b|\bToppserien\b|\bKansallinen Liiga\b|\bDamallsvenskan\b|\bNorthern Super League\b/i;
|
|
123
|
+
const YOUTH_PATTERN = /\bprimavera\b|\bU\d{2}\b|\bunder[- ]?\d{2}\b|\byouth\b|\bjunior(?:en)?\b|\bPremier League 2\b|\bPremier League Cup\b|\bProfessional Development League\b/i;
|
|
124
|
+
function inferCategory(leagueName) {
|
|
125
|
+
if (WOMEN_PATTERN.test(leagueName))
|
|
126
|
+
return "women";
|
|
127
|
+
if (YOUTH_PATTERN.test(leagueName))
|
|
128
|
+
return "youth";
|
|
129
|
+
return "men";
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Maps Opta league names to our DB names when they differ (sponsor names, abbreviations).
|
|
133
|
+
* Key: "normalizedOptaName::normalizedCountry"
|
|
134
|
+
* Value: "normalizedDbName::normalizedDbCountry"
|
|
135
|
+
*/
|
|
136
|
+
const LEAGUE_ALIASES = {
|
|
137
|
+
// Sponsor / commercial names vs generic names
|
|
138
|
+
"first division a::belgium": "jupiler pro league::belgium",
|
|
139
|
+
"primera division::spain": "la liga::spain",
|
|
140
|
+
"mls::usa": "major league soccer::usa",
|
|
141
|
+
"mls::canada": "major league soccer::usa",
|
|
142
|
+
"saudi league::saudi arabia": "pro league::saudi arabia",
|
|
143
|
+
"nike liga::slovakia": "super liga::slovakia",
|
|
144
|
+
"psl::south africa": "premier soccer league::south africa",
|
|
145
|
+
"lpf::panama": "liga panamena de futbol::panama",
|
|
146
|
+
"besta deild::iceland": "urvalsdeild::iceland",
|
|
147
|
+
"liga 1::peru": "primera division::peru",
|
|
148
|
+
"super league::indonesia": "liga 1::indonesia",
|
|
149
|
+
// Opta league-meta.json uses country-prefixed or localized names
|
|
150
|
+
// — aliases also prevent partial-match conflicts where multiple Opta leagues
|
|
151
|
+
// would substring-match the same DB league (e.g. "Bundesliga" vs "Bundesliga Zwei")
|
|
152
|
+
"german bundesliga zwei::germany": "2 bundesliga::germany",
|
|
153
|
+
"english national league::england": "national league::england",
|
|
154
|
+
"spanish segunda division::spain": "segunda division::spain",
|
|
155
|
+
"austrian frauenliga::austria": "frauenliga::austria",
|
|
156
|
+
// Men's
|
|
157
|
+
"croatia prva hnl::croatia": "hnl::croatia",
|
|
158
|
+
"czech first league::czech republic": "czech liga::czech republic",
|
|
159
|
+
"cypriot division 1::cyprus": "1 division::cyprus",
|
|
160
|
+
"saudi arabian league::saudi arabia": "pro league::saudi arabia",
|
|
161
|
+
"chile primera::chile": "primera division::chile",
|
|
162
|
+
"slovenia prvaliga::slovenia": "1 snl::slovenia",
|
|
163
|
+
"azerbaijan premier league::azerbaijan": "premyer liqa::azerbaijan",
|
|
164
|
+
"slovakia 1 liga::slovakia": "super liga::slovakia",
|
|
165
|
+
"south africa psl::south africa": "premier soccer league::south africa",
|
|
166
|
+
"german 3rd liga::germany": "3 liga::germany",
|
|
167
|
+
"albanian kategoria superiore::albania": "superliga::albania",
|
|
168
|
+
"irish premier league::ireland": "premier division::ireland",
|
|
169
|
+
"nigerian premier league::nigeria": "npfl::nigeria",
|
|
170
|
+
"norwegian 1 divisjon::norway": "1 division::norway",
|
|
171
|
+
"icelandic besta deild::iceland": "urvalsdeild::iceland",
|
|
172
|
+
"georgian premier league::georgia": "erovnuli liga::georgia",
|
|
173
|
+
"maltese league::malta": "premier league::malta",
|
|
174
|
+
// Women's
|
|
175
|
+
"english womens super league::england": "fa wsl::england",
|
|
176
|
+
"national womens soccer league::usa": "nwsl women::usa",
|
|
177
|
+
"german womens bundesliga::germany": "frauen bundesliga::germany",
|
|
178
|
+
"french feminine premiere ligue::france": "feminine division 1::france",
|
|
179
|
+
"english wsl 2::england": "womens championship::england",
|
|
180
|
+
"brasileiro feminino a1::brazil": "brasileiro women::brazil",
|
|
181
|
+
"spanish primera federacion femenina::spain": "primera division femenina::spain",
|
|
182
|
+
"2 bundesliga women::germany": "2 frauen bundesliga::germany",
|
|
183
|
+
"icelandic besta deild women::iceland": "urvalsdeild women::iceland",
|
|
184
|
+
"russian superliga women::russia": "supreme division women::russia",
|
|
185
|
+
"nadeshiko league 1::japan": "we league::japan",
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Resolve a league name + country to the DB canonical form.
|
|
189
|
+
* Returns null if no alias exists.
|
|
190
|
+
*/
|
|
191
|
+
function resolveLeagueAlias(normName, normCountry) {
|
|
192
|
+
const alias = LEAGUE_ALIASES[`${normName}::${normCountry}`];
|
|
193
|
+
if (!alias)
|
|
194
|
+
return null;
|
|
195
|
+
const sep = alias.indexOf("::");
|
|
196
|
+
return { name: alias.substring(0, sep), country: alias.substring(sep + 2) };
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/matching/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface MatchCandidate {
|
|
2
|
+
name: string;
|
|
3
|
+
alternateNames?: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface MatchResult<T extends MatchCandidate> {
|
|
6
|
+
item: T;
|
|
7
|
+
score: number;
|
|
8
|
+
matchedVia: "exact" | "fuzzy";
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Match an external entity to a list of DB candidates by name similarity.
|
|
12
|
+
*
|
|
13
|
+
* Compares every combination of `externalNames` × candidate `name + alternateNames`.
|
|
14
|
+
* Returns the best match above the threshold, or null.
|
|
15
|
+
*
|
|
16
|
+
* @param externalNames - External name(s) to match (e.g. main name + alternates)
|
|
17
|
+
* @param candidates - DB records with `name` and optional `alternateNames`
|
|
18
|
+
* @param threshold - Minimum similarity score (default 0.5)
|
|
19
|
+
*/
|
|
20
|
+
export declare function matchByName<T extends MatchCandidate>(externalNames: string[], candidates: T[], threshold?: number): MatchResult<T> | null;
|
|
21
|
+
//# sourceMappingURL=team-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-matcher.d.ts","sourceRoot":"","sources":["../../src/matching/team-matcher.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,cAAc;IACnD,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,cAAc,EAClD,aAAa,EAAE,MAAM,EAAE,EACvB,UAAU,EAAE,CAAC,EAAE,EACf,SAAS,SAAM,GACd,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CA+BvB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchByName = matchByName;
|
|
4
|
+
const string_similarity_js_1 = require("string-similarity-js");
|
|
5
|
+
const normalize_1 = require("./normalize");
|
|
6
|
+
/**
|
|
7
|
+
* Match an external entity to a list of DB candidates by name similarity.
|
|
8
|
+
*
|
|
9
|
+
* Compares every combination of `externalNames` × candidate `name + alternateNames`.
|
|
10
|
+
* Returns the best match above the threshold, or null.
|
|
11
|
+
*
|
|
12
|
+
* @param externalNames - External name(s) to match (e.g. main name + alternates)
|
|
13
|
+
* @param candidates - DB records with `name` and optional `alternateNames`
|
|
14
|
+
* @param threshold - Minimum similarity score (default 0.5)
|
|
15
|
+
*/
|
|
16
|
+
function matchByName(externalNames, candidates, threshold = 0.5) {
|
|
17
|
+
const normExternal = externalNames.map(normalize_1.normalize).filter(Boolean);
|
|
18
|
+
if (normExternal.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
let bestMatch = null;
|
|
21
|
+
let bestScore = 0;
|
|
22
|
+
for (const candidate of candidates) {
|
|
23
|
+
const normCandidateName = (0, normalize_1.normalize)(candidate.name || "");
|
|
24
|
+
const normCandidateAlts = (candidate.alternateNames || []).map(normalize_1.normalize);
|
|
25
|
+
const allCandidateNames = [normCandidateName, ...normCandidateAlts].filter(Boolean);
|
|
26
|
+
for (const en of normExternal) {
|
|
27
|
+
for (const cn of allCandidateNames) {
|
|
28
|
+
if (en === cn) {
|
|
29
|
+
return { item: candidate, score: 1.0, matchedVia: "exact" };
|
|
30
|
+
}
|
|
31
|
+
const score = (0, string_similarity_js_1.stringSimilarity)(en, cn);
|
|
32
|
+
if (score > bestScore) {
|
|
33
|
+
bestScore = score;
|
|
34
|
+
bestMatch = candidate;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (bestMatch && bestScore >= threshold) {
|
|
40
|
+
return { item: bestMatch, score: bestScore, matchedVia: "fuzzy" };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=team-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-matcher.js","sourceRoot":"","sources":["../../src/matching/team-matcher.ts"],"names":[],"mappings":";;AAwBA,kCAmCC;AA3DD,+DAAwD;AACxD,2CAAwC;AAaxC;;;;;;;;;GASG;AACH,SAAgB,WAAW,CACzB,aAAuB,EACvB,UAAe,EACf,SAAS,GAAG,GAAG;IAEf,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,qBAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,IAAI,SAAS,GAAa,IAAI,CAAC;IAC/B,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,iBAAiB,GAAG,IAAA,qBAAS,EAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,iBAAiB,GAAG,CAAC,SAAS,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,qBAAS,CAAC,CAAC;QAC1E,MAAM,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,GAAG,iBAAiB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpF,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;YAC9B,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;gBACnC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;oBACd,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;gBAC9D,CAAC;gBAED,MAAM,KAAK,GAAG,IAAA,uCAAgB,EAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBACvC,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;oBACtB,SAAS,GAAG,KAAK,CAAC;oBAClB,SAAS,GAAG,SAAS,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weekendgoals/weekendgoals-common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1909.22283215374",
|
|
4
4
|
"description": "Weekend Goals Common",
|
|
5
5
|
"private": false,
|
|
6
6
|
"files": [
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@weekendgoals/weekendgoals-types": "^1.0.0",
|
|
19
19
|
"axios": "^1.9.0",
|
|
20
|
-
"mongoose": "^8.20.1"
|
|
20
|
+
"mongoose": "^8.20.1",
|
|
21
|
+
"string-similarity-js": "^2.1.4"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/node": "^24.10.1",
|