@claudinho/core 0.8.16 → 0.8.18
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/index.d.ts +25 -1
- package/dist/index.js +101 -10
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -355,6 +355,30 @@ declare function currentOrNextFixtureForTeam(code: string, opts?: {
|
|
|
355
355
|
/** Sorted list of distinct group letters present in the schedule. */
|
|
356
356
|
declare function groups(fixtures?: Match[]): string[];
|
|
357
357
|
|
|
358
|
+
/** A roster team plus its group letter (A–L). */
|
|
359
|
+
interface TeamInfo extends Team {
|
|
360
|
+
group?: string;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* The 48-team roster from the bundled group-stage fixtures, sorted by name.
|
|
364
|
+
* Placeholder/knockout slots (non-3-letter code or 🏳️) are skipped.
|
|
365
|
+
*/
|
|
366
|
+
declare function allTeams(fixtures?: Match[]): TeamInfo[];
|
|
367
|
+
interface TeamLookup {
|
|
368
|
+
query: string;
|
|
369
|
+
/** The single confident match, or null when the query is ambiguous or unknown. */
|
|
370
|
+
team: TeamInfo | null;
|
|
371
|
+
/** All candidate teams, best-first (1+ whenever anything matched). */
|
|
372
|
+
matches: TeamInfo[];
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Resolve a free-text team name or code to a roster team. Precedence: exact code,
|
|
376
|
+
* exact name, alias, then prefix/substring fuzzy on the name (fuzzy only for
|
|
377
|
+
* queries of 3+ letters, so a 1–2 char query can't substring-match noise). A
|
|
378
|
+
* unique fuzzy hit resolves; multiple hits return as candidates with `team: null`.
|
|
379
|
+
*/
|
|
380
|
+
declare function lookupTeam(query: string, fixtures?: Match[]): TeamLookup;
|
|
381
|
+
|
|
358
382
|
/** One row of a group table. */
|
|
359
383
|
interface StandingRow {
|
|
360
384
|
team: Team;
|
|
@@ -1152,4 +1176,4 @@ declare function formatShareBracket(input: ShareBracketInput, options?: ShareBra
|
|
|
1152
1176
|
/** Compact one-line-per-match bracket for narrow share contexts. */
|
|
1153
1177
|
declare function formatBracketCompactLine(mv: BracketMatchView, opts?: BracketFormatOpts): string;
|
|
1154
1178
|
|
|
1155
|
-
export { BRACKET_STAGE_ORDER, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketTopology, type BracketView, type BuildSignalInput, DEFAULT_COMPETITION, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, EspnAdapter, type EspnAdapterOptions, FLAVOR_LEVELS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FlavorLevel, type FormatOpts, type GroupStandings, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type LiveResult, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type NextFixtureResult, type Outcome, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, type PunditPick, type ResolvedParticipant, SHARE_DISCLAIMER, SHARE_HASHTAG, type ShareBracketInput, type ShareBracketOptions, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type Stage, type StandingRow, type StandingsResult, type Status, type Team, allFixtures, asFlavorLevel, buildBracketTopology, buildBracketView, buildMarketSignal, byKickoff, competitionBase, computeStandings, countdown, currentOrNextFixtureForTeam, deriveFavorite, favoriteStrength, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getStandings, groups, hasSaneDistribution, isFinished, isFlavorLevel, isLive, isReliableMarketSignal, isResolvedNation, isStaleSignal, isValidDate, isValidTimeZone, liveSourceLabel, loadBracketTopology, localDate, makeAdapter, makeMarketProvider, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketSignalRendersFor, marketSourceLabel, matchFlavor, matchKey, matchLocation, mergeLive, nationToFlag, nationToRegion, nextFixtureForTeam, normalizeLang, normalizeOutcomes, outcomeFromScore, parseStandings, parseTeamSlot, resolveCompetition, resolveMarketSource, resolveTz, sanitizeBundledFixture, scoreline, stageLabel, stageLabelI18n, t };
|
|
1179
|
+
export { BRACKET_STAGE_ORDER, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketTopology, type BracketView, type BuildSignalInput, DEFAULT_COMPETITION, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, EspnAdapter, type EspnAdapterOptions, FLAVOR_LEVELS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FlavorLevel, type FormatOpts, type GroupStandings, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type LiveResult, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type NextFixtureResult, type Outcome, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, type PunditPick, type ResolvedParticipant, SHARE_DISCLAIMER, SHARE_HASHTAG, type ShareBracketInput, type ShareBracketOptions, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type Stage, type StandingRow, type StandingsResult, type Status, type Team, type TeamInfo, type TeamLookup, allFixtures, allTeams, asFlavorLevel, buildBracketTopology, buildBracketView, buildMarketSignal, byKickoff, competitionBase, computeStandings, countdown, currentOrNextFixtureForTeam, deriveFavorite, favoriteStrength, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getStandings, groups, hasSaneDistribution, isFinished, isFlavorLevel, isLive, isReliableMarketSignal, isResolvedNation, isStaleSignal, isValidDate, isValidTimeZone, liveSourceLabel, loadBracketTopology, localDate, lookupTeam, makeAdapter, makeMarketProvider, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketSignalRendersFor, marketSourceLabel, matchFlavor, matchKey, matchLocation, mergeLive, nationToFlag, nationToRegion, nextFixtureForTeam, normalizeLang, normalizeOutcomes, outcomeFromScore, parseStandings, parseTeamSlot, resolveCompetition, resolveMarketSource, resolveTz, sanitizeBundledFixture, scoreline, stageLabel, stageLabelI18n, t };
|
package/dist/index.js
CHANGED
|
@@ -2900,6 +2900,62 @@ function groups(fixtures = SCHEDULE) {
|
|
|
2900
2900
|
return [...set].sort();
|
|
2901
2901
|
}
|
|
2902
2902
|
|
|
2903
|
+
// src/teams.ts
|
|
2904
|
+
function norm2(s) {
|
|
2905
|
+
return s.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z]/g, "");
|
|
2906
|
+
}
|
|
2907
|
+
function allTeams(fixtures = allFixtures()) {
|
|
2908
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2909
|
+
for (const m of fixtures) {
|
|
2910
|
+
if (m.stage !== "GROUP") continue;
|
|
2911
|
+
for (const t2 of [m.home, m.away]) {
|
|
2912
|
+
if (!/^[A-Z]{3}$/.test(t2.code) || t2.flag === "\u{1F3F3}\uFE0F") continue;
|
|
2913
|
+
if (!seen.has(t2.code)) seen.set(t2.code, { ...t2, group: m.group ?? void 0 });
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
return [...seen.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
2917
|
+
}
|
|
2918
|
+
var TEAM_ALIASES = {
|
|
2919
|
+
turkey: "TUR",
|
|
2920
|
+
holland: "NED",
|
|
2921
|
+
korea: "KOR",
|
|
2922
|
+
skorea: "KOR",
|
|
2923
|
+
korearepublic: "KOR",
|
|
2924
|
+
republicofkorea: "KOR",
|
|
2925
|
+
czechrepublic: "CZE",
|
|
2926
|
+
congo: "COD",
|
|
2927
|
+
drcongo: "COD",
|
|
2928
|
+
drc: "COD",
|
|
2929
|
+
democraticrepublicofcongo: "COD",
|
|
2930
|
+
democraticrepublicofthecongo: "COD",
|
|
2931
|
+
cotedivoire: "CIV",
|
|
2932
|
+
caboverde: "CPV",
|
|
2933
|
+
bosnia: "BIH",
|
|
2934
|
+
bosniaandherzegovina: "BIH",
|
|
2935
|
+
us: "USA",
|
|
2936
|
+
america: "USA",
|
|
2937
|
+
unitedstatesofamerica: "USA"
|
|
2938
|
+
};
|
|
2939
|
+
function lookupTeam(query, fixtures = allFixtures()) {
|
|
2940
|
+
const roster = allTeams(fixtures);
|
|
2941
|
+
const q = norm2(query);
|
|
2942
|
+
if (!q) return { query, team: null, matches: [] };
|
|
2943
|
+
const byCode = roster.find((t2) => norm2(t2.code) === q);
|
|
2944
|
+
if (byCode) return { query, team: byCode, matches: [byCode] };
|
|
2945
|
+
const byName = roster.find((t2) => norm2(t2.name) === q);
|
|
2946
|
+
if (byName) return { query, team: byName, matches: [byName] };
|
|
2947
|
+
const aliasCode = TEAM_ALIASES[q];
|
|
2948
|
+
if (aliasCode) {
|
|
2949
|
+
const t2 = roster.find((r) => r.code === aliasCode);
|
|
2950
|
+
if (t2) return { query, team: t2, matches: [t2] };
|
|
2951
|
+
}
|
|
2952
|
+
if (q.length < 3) return { query, team: null, matches: [] };
|
|
2953
|
+
const prefix = roster.filter((t2) => norm2(t2.name).startsWith(q));
|
|
2954
|
+
const substr = roster.filter((t2) => norm2(t2.name).includes(q) && !prefix.includes(t2));
|
|
2955
|
+
const matches = [...prefix, ...substr];
|
|
2956
|
+
return { query, team: matches.length === 1 ? matches[0] : null, matches };
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2903
2959
|
// src/standings.ts
|
|
2904
2960
|
function blankRow(team) {
|
|
2905
2961
|
return {
|
|
@@ -4465,7 +4521,8 @@ var PolymarketProvider = class {
|
|
|
4465
4521
|
opts;
|
|
4466
4522
|
name = "polymarket";
|
|
4467
4523
|
async findSignal(match, options) {
|
|
4468
|
-
|
|
4524
|
+
const deadline = options?.deadlineMs != null ? Date.now() + options.deadlineMs : Number.POSITIVE_INFINITY;
|
|
4525
|
+
return (await this.resolveOne(match, options, deadline)).signal;
|
|
4469
4526
|
}
|
|
4470
4527
|
async findSignals(matches, options) {
|
|
4471
4528
|
const signals = /* @__PURE__ */ new Map();
|
|
@@ -4473,7 +4530,7 @@ var PolymarketProvider = class {
|
|
|
4473
4530
|
const deadline = options?.deadlineMs != null ? Date.now() + options.deadlineMs : Number.POSITIVE_INFINITY;
|
|
4474
4531
|
for (const m of matches) {
|
|
4475
4532
|
if (Date.now() >= deadline) break;
|
|
4476
|
-
const r = await this.resolveOne(m, options);
|
|
4533
|
+
const r = await this.resolveOne(m, options, deadline);
|
|
4477
4534
|
if (r.checked) checked.add(m.id);
|
|
4478
4535
|
if (r.signal) signals.set(m.id, r.signal);
|
|
4479
4536
|
}
|
|
@@ -4485,13 +4542,16 @@ var PolymarketProvider = class {
|
|
|
4485
4542
|
* provider/network error — so transient failures are retried, not
|
|
4486
4543
|
* negative-cached.
|
|
4487
4544
|
*/
|
|
4488
|
-
async resolveOne(match, options) {
|
|
4545
|
+
async resolveOne(match, options, deadline = Number.POSITIVE_INFINITY) {
|
|
4489
4546
|
const entry = (this.opts.mapping ?? BUNDLED_MAPPING)[match.id];
|
|
4490
4547
|
const slugs = entry?.eventSlug ? [entry.eventSlug] : deriveEventSlugs(match);
|
|
4491
4548
|
if (slugs.length === 0) return { checked: true };
|
|
4549
|
+
const configured = options?.timeoutMs ?? this.opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
4492
4550
|
try {
|
|
4493
4551
|
for (const slug of slugs) {
|
|
4494
|
-
const
|
|
4552
|
+
const remaining = deadline - Date.now();
|
|
4553
|
+
if (remaining <= 0) return { checked: false };
|
|
4554
|
+
const event = await this.fetchEvent(slug, Math.min(configured, remaining));
|
|
4495
4555
|
const signal = event ? this.toSignal(match, slug, event, options) : void 0;
|
|
4496
4556
|
if (signal) return { signal, checked: true };
|
|
4497
4557
|
}
|
|
@@ -4571,6 +4631,27 @@ var PolymarketProvider = class {
|
|
|
4571
4631
|
return signal.ambiguous ? void 0 : signal;
|
|
4572
4632
|
}
|
|
4573
4633
|
};
|
|
4634
|
+
var POLYMARKET_TOKEN = {
|
|
4635
|
+
SUI: "che",
|
|
4636
|
+
// Switzerland
|
|
4637
|
+
NED: "nld",
|
|
4638
|
+
// Netherlands
|
|
4639
|
+
URU: "ury",
|
|
4640
|
+
// Uruguay
|
|
4641
|
+
POR: "prt",
|
|
4642
|
+
// Portugal
|
|
4643
|
+
CRO: "hrv",
|
|
4644
|
+
// Croatia
|
|
4645
|
+
COD: "cdr",
|
|
4646
|
+
// DR Congo
|
|
4647
|
+
CPV: "cvi"
|
|
4648
|
+
// Cabo Verde
|
|
4649
|
+
};
|
|
4650
|
+
function pmTokens(code) {
|
|
4651
|
+
const c = code.toLowerCase();
|
|
4652
|
+
const alias = POLYMARKET_TOKEN[code.toUpperCase()];
|
|
4653
|
+
return alias && alias !== c ? [alias, c] : [c];
|
|
4654
|
+
}
|
|
4574
4655
|
function deriveEventSlugs(match) {
|
|
4575
4656
|
const home = match.home.code.toLowerCase();
|
|
4576
4657
|
const away = match.away.code.toLowerCase();
|
|
@@ -4578,10 +4659,18 @@ function deriveEventSlugs(match) {
|
|
|
4578
4659
|
if (!/^[a-z]{3}$/.test(home) || !/^[a-z]{3}$/.test(away)) return [];
|
|
4579
4660
|
const utcDate = match.kickoff.slice(0, 10);
|
|
4580
4661
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(utcDate)) return [];
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
];
|
|
4662
|
+
const dates = [utcDate, shiftUtcDate(utcDate, -1)];
|
|
4663
|
+
const homeToks = pmTokens(match.home.code);
|
|
4664
|
+
const awayToks = pmTokens(match.away.code);
|
|
4665
|
+
const slugs = [];
|
|
4666
|
+
for (const d of dates) {
|
|
4667
|
+
for (const h of homeToks) {
|
|
4668
|
+
for (const a of awayToks) {
|
|
4669
|
+
slugs.push(`fifwc-${h}-${a}-${d}`);
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
return [...new Set(slugs)];
|
|
4585
4674
|
}
|
|
4586
4675
|
function slugToken(m) {
|
|
4587
4676
|
return (m.slug ?? "").toLowerCase().split("-").pop() ?? "";
|
|
@@ -4590,10 +4679,10 @@ function isDrawMarket(m) {
|
|
|
4590
4679
|
return slugToken(m) === "draw" || (m.groupItemTitle ?? "").trim().toLowerCase().startsWith("draw");
|
|
4591
4680
|
}
|
|
4592
4681
|
function pickMarket(markets, teamCode, teamName) {
|
|
4593
|
-
const
|
|
4682
|
+
const tokens = pmTokens(teamCode);
|
|
4594
4683
|
const name = teamName.trim().toLowerCase();
|
|
4595
4684
|
const teamMarkets = markets.filter((m) => !isDrawMarket(m));
|
|
4596
|
-
const bySlug = teamMarkets.find((m) => slugToken(m)
|
|
4685
|
+
const bySlug = teamMarkets.find((m) => tokens.includes(slugToken(m)));
|
|
4597
4686
|
if (bySlug) return bySlug;
|
|
4598
4687
|
return teamMarkets.find((m) => (m.groupItemTitle ?? "").trim().toLowerCase() === name);
|
|
4599
4688
|
}
|
|
@@ -4943,6 +5032,7 @@ export {
|
|
|
4943
5032
|
SHARE_DISCLAIMER,
|
|
4944
5033
|
SHARE_HASHTAG,
|
|
4945
5034
|
allFixtures,
|
|
5035
|
+
allTeams,
|
|
4946
5036
|
asFlavorLevel,
|
|
4947
5037
|
buildBracketTopology,
|
|
4948
5038
|
buildBracketView,
|
|
@@ -4991,6 +5081,7 @@ export {
|
|
|
4991
5081
|
liveSourceLabel,
|
|
4992
5082
|
loadBracketTopology,
|
|
4993
5083
|
localDate,
|
|
5084
|
+
lookupTeam,
|
|
4994
5085
|
makeAdapter,
|
|
4995
5086
|
makeMarketProvider,
|
|
4996
5087
|
mapEspnEvent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.18",
|
|
4
4
|
"description": "Domain model, provider adapters (ESPN), standings, bundled schedule, and the read-only Polymarket market-signal sidecar powering Claudinho. Not affiliated with FIFA or Anthropic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|