diff --git a/.vscode/settings.json b/.vscode/settings.json index f9c5a089..ce82118f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,8 +7,7 @@ "*.ts": "$(capture).test.ts,$(capture).d.ts" }, "oxc.typeAware": true, - "js/ts.experimental.useTsgo": false, - "js/ts.tsdk.path": "node_modules/typescript/lib", + "js/ts.experimental.useTsgo": true, "cSpell.language": "de,en", "editor.formatOnSaveMode": "modificationsIfAvailable", diff --git a/Dockerfile b/Dockerfile index d9b7d632..6147493e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,4 +40,4 @@ FROM node:alpine RUN echo "RELEASE_IDENTIFIER=${RELEASE_IDENTIFIER:-debug}" >> /app/.env && \ echo "BUILD_NUMBER=${BUILD_NUMBER:-0}" >> /app/.env - ENTRYPOINT ["node", "--env-file", "/app/.env", "src/app.ts"] + ENTRYPOINT ["node", "--env-file", "/app/.env", "--require", "./src/polyfills.ts", "src/app.ts"] diff --git a/package-lock.json b/package-lock.json index f726bc88..ca2647e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,8 +40,7 @@ "lefthook": "^2.1.3", "oxfmt": "^0.36.0", "oxlint": "^1.51.0", - "oxlint-tsgolint": "^0.16.0", - "typescript": "^6.0.1-rc" + "oxlint-tsgolint": "^0.16.0" }, "engines": { "node": ">=25.6.1" @@ -5412,20 +5411,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/typescript": { - "version": "6.0.1-rc", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.1-rc.tgz", - "integrity": "sha512-7XlzYb+p/7YxX6qSOzwB4mxVFRdAgWWkj1PgAZ+jzldeuFV6Z77vwFbNxHsUXAL/bhlWY2jCT8shLwDJR8337g==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/undici": { "version": "6.21.3", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", diff --git a/package.json b/package.json index 058b259b..19432255 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,7 @@ "lefthook": "^2.1.3", "oxfmt": "^0.36.0", "oxlint": "^1.51.0", - "oxlint-tsgolint": "^0.16.0", - "typescript": "^6.0.1-rc" + "oxlint-tsgolint": "^0.16.0" }, "engines": { "node": ">=25.6.1" diff --git a/src/app.ts b/src/app.ts index 689d5326..bc018c3d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,9 +4,6 @@ import * as sentry from "@sentry/node"; import { readConfig, databasePath, args } from "#/service/config.ts"; import log from "#log"; -import { Temporal } from "@js-temporal/polyfill"; -import "#/polyfills.ts"; - import * as kysely from "#/storage/db/db.ts"; import type { ReactionHandler } from "#/handler/ReactionHandler.ts"; @@ -58,16 +55,6 @@ log.info(`Bot starting up...${release ? ` (release: ${release})` : ""}`); const config = await readConfig(); -// This polyfill requires that Temporal is already available in the runtime -// We cannot add it in the polyfills.ts because that file is also used as --require argument for ts-node -// TODO: Remove this once temporal is available in Node.js, see: https://github.com/nodejs/node/issues/57127 -if (typeof Date.prototype.toTemporalInstant !== "function") { - // biome-ignore lint/suspicious/noExplicitAny: hack - (Date.prototype as any).toTemporalInstant = function () { - return Temporal.Instant.fromEpochMilliseconds(this.getTime()); - }; -} - if (config.sentry?.dsn) { sentry.init({ dsn: config.sentry.dsn, diff --git a/src/commands/lauscher.ts b/src/commands/lauscher.ts index 2ddc27b3..058a51a4 100644 --- a/src/commands/lauscher.ts +++ b/src/commands/lauscher.ts @@ -16,7 +16,6 @@ import type { ApplicationCommand } from "#/commands/command.ts"; import type { BotContext } from "#/context.ts"; import assertNever from "#/utils/assertNever.ts"; import { getPlaybackStats, setUserRegistration, type TrackStat } from "#/service/lauscher.ts"; -import { Temporal } from "@js-temporal/polyfill"; import { truncateToLength } from "#/utils/stringUtils.ts"; import { chunkArray } from "#/utils/arrayUtils.ts"; import { Vec2 } from "#/utils/math.ts"; diff --git a/src/commands/vote.ts b/src/commands/vote.ts index c830f463..2cbfe8d3 100644 --- a/src/commands/vote.ts +++ b/src/commands/vote.ts @@ -1,7 +1,6 @@ import { parseArgs, type ParseArgsConfig } from "node:util"; import { cleanContent } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { MessageCommand } from "#/commands/command.ts"; import type { BotContext } from "#/context.ts"; diff --git a/src/commands/woisvote.ts b/src/commands/woisvote.ts index 42b01a7a..f31ef869 100644 --- a/src/commands/woisvote.ts +++ b/src/commands/woisvote.ts @@ -1,5 +1,3 @@ -import { Temporal } from "@js-temporal/polyfill"; // TODO: Remove once Node.js ships temporal - import { type CommandInteraction, type Message, diff --git a/src/context.ts b/src/context.ts index 4d6d8367..ba5eb407 100644 --- a/src/context.ts +++ b/src/context.ts @@ -15,7 +15,6 @@ import type { } from "discord.js"; import { ChannelType } from "discord.js"; import { SpotifyApi } from "@spotify/web-api-ts-sdk"; -import { Temporal } from "@js-temporal/polyfill"; import type { UserMapEntry } from "#/commands/aoc.ts"; import { readConfig } from "#/service/config.ts"; diff --git a/src/handler/reaction/quoteHandler.ts b/src/handler/reaction/quoteHandler.ts index bfb0bb0e..b87c46bc 100644 --- a/src/handler/reaction/quoteHandler.ts +++ b/src/handler/reaction/quoteHandler.ts @@ -9,7 +9,6 @@ import { type GuildTextBasedChannel, hyperlink, } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { BotContext, QuoteConfig } from "#/context.ts"; import type { ReactionHandler } from "../ReactionHandler.ts"; diff --git a/src/polyfills.ts b/src/polyfills.ts index c7787152..ec2e40c8 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -1,4 +1,4 @@ -import type { Temporal } from "@js-temporal/polyfill"; +import { Temporal as PolyfillTemporal } from "@js-temporal/polyfill"; declare global { // type polyfill for Math.sumPrecise (currently in stage 2): @@ -13,10 +13,15 @@ declare global { getOrInsert(key: K, defaultValue: V): V; getOrInsertComputed(key: TK, callbackFunction: (key: TK) => V): V; } +} - interface Date { - toTemporalInstant(): Temporal.Instant; - } +globalThis.Temporal = PolyfillTemporal as typeof Temporal; + +// TODO: Remove this once temporal is available in Node.js, see: https://github.com/nodejs/node/issues/57127 +if (typeof Date.prototype.toTemporalInstant !== "function") { + Date.prototype.toTemporalInstant = function () { + return Temporal.Instant.fromEpochMilliseconds(this.getTime()); + }; } if (typeof Math.sumPrecise !== "function") { diff --git a/src/service/ban.ts b/src/service/ban.ts index 3932c166..4d8e2dec 100644 --- a/src/service/ban.ts +++ b/src/service/ban.ts @@ -1,6 +1,5 @@ import { time, type GuildMember, type User, TimestampStyles } from "discord.js"; import * as sentry from "@sentry/node"; -import { Temporal } from "@js-temporal/polyfill"; import type { BotContext } from "#/context.ts"; import * as ban from "#/storage/ban.ts"; diff --git a/src/service/fadingMessage.ts b/src/service/fadingMessage.ts index 7e1929e3..c9c1f741 100644 --- a/src/service/fadingMessage.ts +++ b/src/service/fadingMessage.ts @@ -1,6 +1,5 @@ import type { TextChannel } from "discord.js"; import * as sentry from "@sentry/node"; -import { Temporal } from "@js-temporal/polyfill"; import type { BotContext } from "#/context.ts"; diff --git a/src/service/lauscher.ts b/src/service/lauscher.ts index bb81fc20..86b9c350 100644 --- a/src/service/lauscher.ts +++ b/src/service/lauscher.ts @@ -1,4 +1,3 @@ -import type { Temporal } from "@js-temporal/polyfill"; import type { Activity, User } from "discord.js"; import type { BotContext } from "#/context.ts"; diff --git a/src/service/loot.ts b/src/service/loot.ts index 54e4929f..340256e2 100644 --- a/src/service/loot.ts +++ b/src/service/loot.ts @@ -1,5 +1,4 @@ import type { User, Snowflake, Message } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { LootId, LootInsertable, LootOrigin } from "#/storage/db/model.ts"; import type { LootAttributeKindId, LootKindId } from "./lootData.ts"; diff --git a/src/service/lootDrop.ts b/src/service/lootDrop.ts index cc092308..f3cfa582 100644 --- a/src/service/lootDrop.ts +++ b/src/service/lootDrop.ts @@ -17,7 +17,6 @@ import { type MessageComponentInteraction, type BaseMessageOptions, } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import * as sentry from "@sentry/node"; import type { BotContext } from "#/context.ts"; diff --git a/src/service/poll.ts b/src/service/poll.ts index cb1c3c0a..fb24f254 100644 --- a/src/service/poll.ts +++ b/src/service/poll.ts @@ -1,5 +1,4 @@ import type { GuildMember, Message, MessageReaction, TextBasedChannel, User } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import * as legacyDelayedPoll from "#/service/delayedPollLegacy.ts"; import type { Poll, PollId } from "#/storage/db/model.ts"; diff --git a/src/service/pollEmbed.ts b/src/service/pollEmbed.ts index cbbe64d4..ccf213bd 100644 --- a/src/service/pollEmbed.ts +++ b/src/service/pollEmbed.ts @@ -8,7 +8,6 @@ import { TimestampStyles, type User, } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; export const LETTERS = [ ":regional_indicator_a:", diff --git a/src/service/roll.ts b/src/service/roll.ts index 85ebff3f..8e98f00a 100644 --- a/src/service/roll.ts +++ b/src/service/roll.ts @@ -1,5 +1,4 @@ import { cleanContent, type APIEmbed, type TextChannel, type User } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; export async function rollInChannel( author: User, diff --git a/src/service/voiceState.ts b/src/service/voiceState.ts index f0106c6e..66ed5970 100644 --- a/src/service/voiceState.ts +++ b/src/service/voiceState.ts @@ -1,5 +1,4 @@ import type { VoiceState } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { BotContext } from "#/context.ts"; import log from "#log"; diff --git a/src/storage/ban.ts b/src/storage/ban.ts index 26a6dd81..c4ec9145 100644 --- a/src/storage/ban.ts +++ b/src/storage/ban.ts @@ -1,5 +1,4 @@ import type { GuildMember, Snowflake, User } from "discord.js"; -import type { Temporal } from "@js-temporal/polyfill"; import type { Ban } from "./db/model.ts"; import db from "#db"; diff --git a/src/storage/db/date-plugin.ts b/src/storage/db/date-plugin.ts index fc5ef22b..3694740a 100644 --- a/src/storage/db/date-plugin.ts +++ b/src/storage/db/date-plugin.ts @@ -6,7 +6,6 @@ import type { RootOperationNode, UnknownRow, } from "kysely"; -import { Temporal } from "@js-temporal/polyfill"; import log from "#log"; diff --git a/src/storage/emote.ts b/src/storage/emote.ts index 95e979bb..06fa75f0 100644 --- a/src/storage/emote.ts +++ b/src/storage/emote.ts @@ -1,5 +1,4 @@ import { sql } from "kysely"; -import { Temporal } from "@js-temporal/polyfill"; import type { Message, Snowflake } from "discord.js"; import type { Emote } from "./db/model.ts"; diff --git a/src/storage/fadingMessage.ts b/src/storage/fadingMessage.ts index 2eb88c06..16d4450b 100644 --- a/src/storage/fadingMessage.ts +++ b/src/storage/fadingMessage.ts @@ -1,5 +1,4 @@ import type { Message } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { FadingMessage } from "./db/model.ts"; import db from "#db"; diff --git a/src/storage/lauscher.ts b/src/storage/lauscher.ts index bed52a8d..b104a719 100644 --- a/src/storage/lauscher.ts +++ b/src/storage/lauscher.ts @@ -1,4 +1,3 @@ -import { Temporal } from "@js-temporal/polyfill"; // TODO: Remove once Node.js ships temporal import type { User } from "discord.js"; import type { LauscherRegistration, LauscherSpotifyLogEntry } from "#/storage/db/model.ts"; diff --git a/src/storage/loot.ts b/src/storage/loot.ts index c39f6dae..da3229ae 100644 --- a/src/storage/loot.ts +++ b/src/storage/loot.ts @@ -8,7 +8,6 @@ import type { User, } from "discord.js"; import { type ExpressionBuilder, sql } from "kysely"; -import type { Temporal } from "@js-temporal/polyfill"; import type { BotContext } from "#/context.ts"; import type { diff --git a/src/storage/poll.ts b/src/storage/poll.ts index b5d86c39..dcbfcba8 100644 --- a/src/storage/poll.ts +++ b/src/storage/poll.ts @@ -1,5 +1,4 @@ import type { Snowflake } from "discord.js"; -import type { Temporal } from "@js-temporal/polyfill"; import db from "#db"; import type { Poll, PollAnswer, PollId, PollOption, PollOptionId } from "./db/model.ts"; diff --git a/src/storage/reminders.ts b/src/storage/reminders.ts index 8172c583..2c183196 100644 --- a/src/storage/reminders.ts +++ b/src/storage/reminders.ts @@ -1,5 +1,4 @@ import type { Snowflake, User } from "discord.js"; -import { Temporal } from "@js-temporal/polyfill"; import type { Reminder } from "./db/model.ts"; diff --git a/src/storage/woisAction.ts b/src/storage/woisAction.ts index 21df81ad..5be29bb2 100644 --- a/src/storage/woisAction.ts +++ b/src/storage/woisAction.ts @@ -1,5 +1,4 @@ import type { Message, PartialMessage, Snowflake, User } from "discord.js"; -import type { Temporal } from "@js-temporal/polyfill"; import type { WoisAction } from "./db/model.ts"; import db from "#db"; diff --git a/src/utils/dateUtils.ts b/src/utils/dateUtils.ts index e104d9c2..ab5fb00e 100644 --- a/src/utils/dateUtils.ts +++ b/src/utils/dateUtils.ts @@ -1,5 +1,3 @@ -import { Temporal } from "@js-temporal/polyfill"; // TODO: Remove once Node.js ships temporal - const timeFormatter = new Intl.DateTimeFormat("de-DE", { hour: "2-digit", minute: "2-digit",