Replace backend submodule with Elysia/Bun sportsmanager backend
This commit is contained in:
-1
Submodule apps/backend deleted from 3dd31e693b
@@ -0,0 +1,42 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
**/*.trace
|
||||
**/*.zip
|
||||
**/*.tar.gz
|
||||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
@@ -0,0 +1,15 @@
|
||||
# Elysia with Bun runtime
|
||||
|
||||
## Getting Started
|
||||
To get started with this template, simply paste this command into your terminal:
|
||||
```bash
|
||||
bun create elysia ./elysia-example
|
||||
```
|
||||
|
||||
## Development
|
||||
To start the development server run:
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
|
||||
Open http://localhost:3000/ with your browser to see the result.
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "backend",
|
||||
"version": "1.0.50",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "bun run --watch src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"elysia": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
},
|
||||
"module": "src/index.js"
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
import { Elysia } from "elysia";
|
||||
|
||||
const isDev = true;
|
||||
const config = {
|
||||
idFormat: isDev ? "utf8" : "base64url",
|
||||
};
|
||||
|
||||
class Sportsmanager {
|
||||
private baseUrl: string;
|
||||
private params: Record<string, string>;
|
||||
|
||||
public constructor(baseUrl, params = {}) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.params = {
|
||||
...params,
|
||||
format: "json",
|
||||
option: "com_sportsmanager",
|
||||
view: "sportsmanager",
|
||||
};
|
||||
}
|
||||
|
||||
private fetch = (params, options) =>
|
||||
fetch(
|
||||
`${this.baseUrl}/index.php?${new URLSearchParams({
|
||||
...this.params,
|
||||
...params,
|
||||
}).toString()}`,
|
||||
options,
|
||||
);
|
||||
|
||||
private id = (id: string | number) =>
|
||||
Buffer.from(`sportsmanager:${new URL(this.baseUrl).host}:${id}`).toString(
|
||||
config.idFormat,
|
||||
);
|
||||
private number = (value: string | number | null | undefined) =>
|
||||
(value ?? null) !== null && !isNaN(+value) ? Number(value) : null;
|
||||
private teamName = (value: string) => value.replace("(NR)", "");
|
||||
public getOverview = async () => {
|
||||
const resp = await this.fetch({ content: "aktuelle_begegnungen" });
|
||||
|
||||
return resp
|
||||
.json()
|
||||
.then(({ data: { running_matches, finished_matches, next_matches } }) => {
|
||||
return [...running_matches, ...finished_matches, ...next_matches]
|
||||
.filter(({ zeitpunkt }) => !!zeitpunkt)
|
||||
.sort((a, b) => {
|
||||
if (a.zeitpunkt === b.zeitpunkt) {
|
||||
return Number(a.begegnung_id) < Number(b.begegnung_id) ? -1 : 1;
|
||||
}
|
||||
|
||||
return a.zeitpunkt < b.zeitpunkt ? -1 : 1;
|
||||
})
|
||||
.map((match) => {
|
||||
return {
|
||||
id: this.id(match.begegnung_id),
|
||||
scheduledAt: new Date(match.zeitpunkt),
|
||||
homeTeam: {
|
||||
id: this.id(`${match.heim_team_id}:${match.heim_teamgruppe}`),
|
||||
name: this.teamName(match.heim_name),
|
||||
logoUrl: match.heim_bild || null,
|
||||
goals: this.number(match.heim_punkte),
|
||||
points: this.number(match.heim_spielpunkte),
|
||||
},
|
||||
awayTeam: {
|
||||
id: this.id(`${match.gast_team_id}:${match.gast_teamgruppe}`),
|
||||
name: this.teamName(match.gast_name),
|
||||
logoUrl: match.gast_bild || null,
|
||||
goals: this.number(match.gast_punkte),
|
||||
points: this.number(match.gast_spielpunkte),
|
||||
},
|
||||
event: {
|
||||
id: this.id(match.veranstaltung_id),
|
||||
name: match.bezeichnung,
|
||||
matchday: match.spieltag_titel || match.spieltag,
|
||||
},
|
||||
tableNumber: match.tisch ? `${match.tisch}` : null,
|
||||
isNonSmoking: Boolean(
|
||||
match.nichtraucherschutz || match.heim_name.includes("(NR)"),
|
||||
),
|
||||
status:
|
||||
this.number(match.heim_punkte) !== null &&
|
||||
this.number(match.gast_punkte) !== null
|
||||
? Number(match.zwischenergebnis)
|
||||
? "LIVE"
|
||||
: Number(match.unbestaetigtes_ergebnis_id)
|
||||
? "AWAITING_APPROVAL"
|
||||
: "COMPLETED"
|
||||
: "SCHEDULED",
|
||||
// orig: match,
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
public getMatch = (id: string) =>
|
||||
this.fetch({
|
||||
content: "aktuelle_begegnungen",
|
||||
task: "begegnung_spielplan",
|
||||
id,
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then(({ data }) => {
|
||||
const {
|
||||
begegnung,
|
||||
heim_team,
|
||||
heim_spieler,
|
||||
gast_team,
|
||||
gast_spieler,
|
||||
veranstaltung,
|
||||
modus,
|
||||
spiele,
|
||||
spielort,
|
||||
} = data;
|
||||
const player = (s) => ({
|
||||
id: this.id(s.spieler_id),
|
||||
name: `${s.vorname} ${s.nachname}`,
|
||||
firstName: s.vorname,
|
||||
lastName: s.nachname,
|
||||
imageUrl: s.bild,
|
||||
});
|
||||
const slotPlayer = (game, key) =>
|
||||
game && game[`${key}_id`]
|
||||
? {
|
||||
id: this.id(game[`${key}_id`]),
|
||||
firstName: game[`${key}_vorname`],
|
||||
lastName: game[`${key}_nachname`],
|
||||
imageUrl: game[`${key}_bild`],
|
||||
}
|
||||
: null;
|
||||
return {
|
||||
id: this.id(begegnung.begegnung_id),
|
||||
scheduledAt: new Date(begegnung.zeitpunkt),
|
||||
homeTeam: {
|
||||
id: this.id(`${heim_team.team_id}:${heim_team.teamgruppe_id}`),
|
||||
name: heim_team.teamname,
|
||||
logoUrl: heim_team.teambild,
|
||||
goals: this.number(begegnung.heim_punkte),
|
||||
points: this.number(begegnung.heim_spielpunkte),
|
||||
},
|
||||
awayTeam: {
|
||||
id: this.id(`${gast_team.team_id}:${gast_team.teamgruppe_id}`),
|
||||
name: gast_team.teamname,
|
||||
logoUrl: gast_team.teambild,
|
||||
goals: this.number(begegnung.gast_punkte),
|
||||
points: this.number(begegnung.gast_spielpunkte),
|
||||
},
|
||||
event: {
|
||||
id: this.id(veranstaltung.veranstaltung_id),
|
||||
name: veranstaltung.bezeichnung,
|
||||
matchday: begegnung.spieltag_titel || begegnung.spieltag,
|
||||
},
|
||||
venue: spielort
|
||||
? {
|
||||
name: spielort.name,
|
||||
}
|
||||
: undefined,
|
||||
tableNumber: begegnung.tisch ? `${begegnung.tisch}` : null,
|
||||
isNonSmoking: Boolean(
|
||||
begegnung.nichtraucherschutz || heim_team.teamname.includes("(NR)"),
|
||||
),
|
||||
status:
|
||||
this.number(begegnung.heim_punkte) !== null &&
|
||||
this.number(begegnung.gast_punkte) !== null
|
||||
? Number(begegnung.zwischenergebnis)
|
||||
? "LIVE"
|
||||
: Number(begegnung.unbestaetigtes_ergebnis_id)
|
||||
? "AWAITING_APPROVAL"
|
||||
: "COMPLETED"
|
||||
: "SCHEDULED",
|
||||
|
||||
homeRosters: heim_spieler.map(player),
|
||||
awayRosters: gast_spieler.map(player),
|
||||
slots: Object.values(
|
||||
modus.modus.split(",").reduce((acc, cur, idx) => {
|
||||
const game = spiele[idx] ?? null;
|
||||
if (!acc[cur]) {
|
||||
acc[cur] = {
|
||||
key: cur,
|
||||
type:
|
||||
cur[0] === "E"
|
||||
? "SINGLE"
|
||||
: cur[0] === "D"
|
||||
? "DOUBLE"
|
||||
: "SHOOT_OUT",
|
||||
sets: [],
|
||||
home: { positionKey: cur.substring(0, 2) },
|
||||
away: { positionKey: cur.substring(2, 4) },
|
||||
};
|
||||
|
||||
switch (acc[cur].type) {
|
||||
case "SINGLE":
|
||||
acc[cur].home.players = [
|
||||
slotPlayer(game, "heim_spieler_1"),
|
||||
];
|
||||
acc[cur].away.players = [
|
||||
slotPlayer(game, "gast_spieler_1"),
|
||||
];
|
||||
break;
|
||||
case "DOUBLE":
|
||||
acc[cur].home.players = [
|
||||
slotPlayer(game, "heim_spieler_1"),
|
||||
slotPlayer(game, "heim_spieler_2"),
|
||||
];
|
||||
acc[cur].away.players = [
|
||||
slotPlayer(game, "gast_spieler_1"),
|
||||
slotPlayer(game, "gast_spieler_2"),
|
||||
];
|
||||
break;
|
||||
case "SHOOT_OUT":
|
||||
acc[cur].home.players = null;
|
||||
acc[cur].away.players = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const set = game
|
||||
? {
|
||||
homeGoals: this.number(game.teamspiel_heim_punkte),
|
||||
awayGoals: this.number(game.teamspiel_gast_punkte),
|
||||
}
|
||||
: null;
|
||||
acc[cur].sets.push(set);
|
||||
return acc;
|
||||
}, {}),
|
||||
),
|
||||
// orig: data,
|
||||
};
|
||||
});
|
||||
|
||||
public getMatchStats = async (id: string) => {
|
||||
const match = await this.fetch({
|
||||
content: "aktuelle_begegnungen",
|
||||
task: "begegnung_spielplan",
|
||||
id,
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((r) => r.data);
|
||||
|
||||
const teams = {
|
||||
[match.heim_team.team_id]: {
|
||||
id: this.id(
|
||||
`${match.heim_team.team_id}:${match.heim_team.teamgruppe_id}`,
|
||||
),
|
||||
name: match.heim_team.teamname,
|
||||
logoUrl: match.heim_team.teambild,
|
||||
},
|
||||
|
||||
[match.gast_team.team_id]: {
|
||||
id: this.id(
|
||||
`${match.gast_team.team_id}:${match.gast_team.teamgruppe_id}`,
|
||||
),
|
||||
name: match.gast_team.teamname,
|
||||
logoUrl: match.gast_team.teambild,
|
||||
},
|
||||
};
|
||||
const [homeTeam, awayTeam] = await Promise.all([
|
||||
this.fetch({
|
||||
content: "teams",
|
||||
task: "team_details",
|
||||
id: match.heim_team.team_id,
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((r) => r.data),
|
||||
this.fetch({
|
||||
content: "teams",
|
||||
task: "team_details",
|
||||
id: match.gast_team.team_id,
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((r) => r.data),
|
||||
]);
|
||||
|
||||
const homeTeamMatches = homeTeam.begegnungen
|
||||
.filter((a) => {
|
||||
return (
|
||||
!(!a.heim_spielpunkte && !a.gast_spielpunkte) &&
|
||||
a.zeitpunkt < match.begegnung.zeitpunkt
|
||||
);
|
||||
})
|
||||
.sort((a, b) => (a.zeitpunkt < b.zeitpunkt ? 1 : -1));
|
||||
const home = {
|
||||
stats: homeTeamMatches.reduce(
|
||||
(acc, match, index) => {
|
||||
const weight = Math.max(0.2, 1 - index * 0.8);
|
||||
const isHome = Number(match.auswaerts) === 0;
|
||||
|
||||
const myGoals = isHome
|
||||
? match.heim_spielpunkte
|
||||
: match.gast_spielpunkte;
|
||||
const oppGoals = isHome
|
||||
? match.gast_spielpunkte
|
||||
: match.heim_spielpunkte;
|
||||
|
||||
// Punkte für Ausgang (Sieg = 1, Remis = 0.5, Niederlage = 0)
|
||||
const resultPoints =
|
||||
myGoals > oppGoals ? 1 : myGoals === oppGoals ? 0.5 : 0;
|
||||
// Torverhältnis-Faktor (verhindert Division durch 0 bei 0 Gegentoren)
|
||||
const goalFactor = (myGoals + 1) / (oppGoals + 1);
|
||||
|
||||
acc.weightSum += weight;
|
||||
acc.scoreSum += (resultPoints * 0.6 + goalFactor * 0.4) * weight;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
weightSum: 0,
|
||||
scoreSum: 0,
|
||||
},
|
||||
),
|
||||
form: homeTeamMatches
|
||||
.slice(0, 5)
|
||||
.reverse()
|
||||
.map((b) => {
|
||||
if (b.heim_spielpunkte === b.gast_spielpunkte) {
|
||||
return "DRAW";
|
||||
}
|
||||
return b.auswaerts
|
||||
? b.heim_spielpunkte < b.gast_spielpunkte
|
||||
? "WIN"
|
||||
: "LOST"
|
||||
: b.heim_spielpunkte < b.gast_spielpunkte
|
||||
? "LOST"
|
||||
: "WIN";
|
||||
}),
|
||||
};
|
||||
|
||||
const awayTeamMatches = awayTeam.begegnungen
|
||||
.filter((a) => {
|
||||
return (
|
||||
!(!a.heim_spielpunkte && !a.gast_spielpunkte) &&
|
||||
a.zeitpunkt < match.begegnung.zeitpunkt
|
||||
);
|
||||
})
|
||||
.sort((a, b) => (a.zeitpunkt < b.zeitpunkt ? 1 : -1));
|
||||
|
||||
const away = {
|
||||
stats: awayTeamMatches.reduce(
|
||||
(acc, match, index) => {
|
||||
const weight = Math.max(0.2, 1 - index * 0.8);
|
||||
const isHome = Number(match.auswaerts) === 0;
|
||||
|
||||
const myGoals = isHome
|
||||
? match.heim_spielpunkte
|
||||
: match.gast_spielpunkte;
|
||||
const oppGoals = isHome
|
||||
? match.gast_spielpunkte
|
||||
: match.heim_spielpunkte;
|
||||
|
||||
// Punkte für Ausgang (Sieg = 1, Remis = 0.5, Niederlage = 0)
|
||||
const resultPoints =
|
||||
myGoals > oppGoals ? 1 : myGoals === oppGoals ? 0.5 : 0;
|
||||
// Torverhältnis-Faktor (verhindert Division durch 0 bei 0 Gegentoren)
|
||||
const goalFactor = (myGoals + 1) / (oppGoals + 1);
|
||||
|
||||
acc.weightSum += weight;
|
||||
acc.scoreSum += (resultPoints * 0.6 + goalFactor * 0.4) * weight;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
weightSum: 0,
|
||||
scoreSum: 0,
|
||||
},
|
||||
),
|
||||
form: awayTeamMatches
|
||||
.slice(0, 5)
|
||||
.reverse()
|
||||
.map((b) => {
|
||||
if (b.heim_spielpunkte === b.gast_spielpunkte) {
|
||||
return "DRAW";
|
||||
}
|
||||
return b.auswaerts
|
||||
? b.heim_spielpunkte < b.gast_spielpunkte
|
||||
? "WIN"
|
||||
: "LOST"
|
||||
: b.heim_spielpunkte < b.gast_spielpunkte
|
||||
? "LOST"
|
||||
: "WIN";
|
||||
}),
|
||||
};
|
||||
|
||||
const homePower =
|
||||
home.stats.weightSum > 0 ? home.stats.scoreSum / home.stats.weightSum : 1;
|
||||
const awayPower =
|
||||
away.stats.weightSum > 0 ? away.stats.scoreSum / away.stats.weightSum : 1;
|
||||
|
||||
// 4. Heimvorteil für das anstehende Match draufschlagen (+12% auf die Power)
|
||||
const finalHomePower = homePower * 1.12;
|
||||
const finalAwayPower = awayPower;
|
||||
|
||||
// Gesamte Power des Matches
|
||||
const totalPower = finalHomePower + finalAwayPower;
|
||||
|
||||
// Grundwahrscheinlichkeiten für Sieg
|
||||
const rawHomeProb = finalHomePower / totalPower;
|
||||
const rawAwayProb = finalAwayPower / totalPower;
|
||||
|
||||
// 5. Unentschieden extrahieren
|
||||
// Je näher die "Power" der beiden Teams beieinander liegt, desto höher die Remis-Chance
|
||||
const powerDiff = Math.abs(finalHomePower - finalAwayPower);
|
||||
const drawPercent = Math.round(Math.max(15, 26 - powerDiff * 15));
|
||||
|
||||
// Rest-Prozente auf Heim- und Auswärtssieg aufteilen
|
||||
const restPercent = 100 - drawPercent;
|
||||
const homePercent = Math.round(rawHomeProb * restPercent);
|
||||
const awayPercent = Math.round(rawAwayProb * restPercent);
|
||||
|
||||
return {
|
||||
prediction: {
|
||||
homeWinChance: homePercent,
|
||||
drawChance: drawPercent,
|
||||
awayWinChance: awayPercent,
|
||||
},
|
||||
form: {
|
||||
home: home.form,
|
||||
away: away.form,
|
||||
},
|
||||
standing: Number(match.veranstaltung.tabellenwertung)
|
||||
? {
|
||||
home: {
|
||||
pos: Number(match.heim_team.platz),
|
||||
name: match.heim_team.teamname,
|
||||
logo: match.heim_team.teambild,
|
||||
games:
|
||||
match.heim_team.siege +
|
||||
match.heim_team.unentschieden +
|
||||
match.heim_team.niederlagen,
|
||||
points: match.heim_team.begegnungspunkte,
|
||||
diff: `${match.heim_team.spielpunkte_differenz > 0 ? "+" : ""}${match.heim_team.spielpunkte_differenz}`,
|
||||
},
|
||||
away: {
|
||||
pos: Number(match.gast_team.platz),
|
||||
name: match.gast_team.teamname,
|
||||
logo: match.gast_team.teambild,
|
||||
games:
|
||||
match.gast_team.siege +
|
||||
match.gast_team.unentschieden +
|
||||
match.gast_team.niederlagen,
|
||||
points: match.gast_team.begegnungspunkte,
|
||||
diff: `${match.gast_team.spielpunkte_differenz > 0 ? "+" : ""}${match.gast_team.spielpunkte_differenz}`,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
firstLeg: match.hinspiel
|
||||
? {
|
||||
homeTeam: {
|
||||
...teams[match.hinspiel.heim_team_id],
|
||||
goals: Number(match.hinspiel.heim_punkte),
|
||||
points: Number(match.hinspiel.heim_spielpunkte),
|
||||
},
|
||||
awayTeam: {
|
||||
...teams[match.hinspiel.gast_team_id],
|
||||
goals: Number(match.hinspiel.gast_punkte),
|
||||
points: Number(match.hinspiel.gast_spielpunkte),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
// orig: { teams, home, away, match, homeTeam, awayTeam },
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const systems = Object.fromEntries(
|
||||
[
|
||||
["https://dtfb.de", Sportsmanager],
|
||||
["https://kickern-hamburg.de", Sportsmanager, { spielort_heim: "1" }],
|
||||
["https://nwtfv.com", Sportsmanager],
|
||||
["https://stfv.de", Sportsmanager],
|
||||
["https://ntfv.de", Sportsmanager, { spielort_heim: "1" }],
|
||||
].map(([domain, Instance, params]) => [
|
||||
new URL(domain).host,
|
||||
new Instance(domain, params),
|
||||
]),
|
||||
);
|
||||
|
||||
const app = new Elysia()
|
||||
.derive(({ error }) => ({
|
||||
resolveGlobalId(id) {
|
||||
try {
|
||||
const [, system, remoteId] = Buffer.from(id, config.idFormat)
|
||||
.toString("utf8")
|
||||
.split(":");
|
||||
const provider = systems[system];
|
||||
return { provider, remoteId };
|
||||
} catch (ex) {
|
||||
return { error: error(400, "") };
|
||||
}
|
||||
},
|
||||
}))
|
||||
.group("/v1", (v1) =>
|
||||
v1
|
||||
.get("/matches", async () => {
|
||||
return Promise.all(
|
||||
Object.values(systems).map((o) => o.getOverview()),
|
||||
).then((r) => r.flat());
|
||||
})
|
||||
.get("/matches/:id", async ({ params: { id }, resolveGlobalId }) => {
|
||||
const { provider, remoteId } = resolveGlobalId(id);
|
||||
|
||||
return provider.getMatch(remoteId);
|
||||
})
|
||||
.get(
|
||||
"/matches/:id/stats",
|
||||
async ({ params: { id }, resolveGlobalId }) => {
|
||||
const { provider, remoteId } = resolveGlobalId(id);
|
||||
|
||||
return provider.getMatchStats(remoteId);
|
||||
},
|
||||
),
|
||||
)
|
||||
.listen({ port: 3000, host: "0.0.0.0" });
|
||||
|
||||
console.log(
|
||||
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
|
||||
);
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "ES2022", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
"types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user