From 8f5eed5151e5228b250c951b49d97899edecfe81 Mon Sep 17 00:00:00 2001 From: Mir Arif Hasan Date: Mon, 28 Jul 2025 21:32:14 +0600 Subject: [PATCH] chore: migrate to `@db.Timestamptz(3)` and remove `luxon` dependency (#5283) * feat: remove deprecated env sync * feat: using infraConfig in bootstrap * chore: migrate to TIMESTAMPTZ and remove luxon dependency * chore: remove luxon deps * Revert "feat: using infraConfig in bootstrap" This reverts commit 147dba632f095dad816afdd4e46ed736e8a3b8ff. * chore: cleanup --- packages/hoppscotch-backend/package.json | 2 - .../migration.sql | 53 ++++++++++++++++++ .../prisma/migrations/migration_lock.toml | 4 +- .../hoppscotch-backend/prisma/schema.prisma | 54 +++++++++---------- .../src/auth/auth.service.ts | 22 ++++---- .../hoppscotch-backend/src/auth/helper.ts | 27 +++++----- .../src/auth/strategies/microsoft.strategy.ts | 7 +-- .../src/guards/infra-token.guard.ts | 5 +- .../src/guards/rest-pat-auth.guard.ts | 19 ++++--- .../src/mailer/templates/team-invitation.hbs | 2 +- .../src/mailer/templates/user-invitation.hbs | 2 +- packages/hoppscotch-backend/src/utils.ts | 8 +-- pnpm-lock.yaml | 12 ----- 13 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 packages/hoppscotch-backend/prisma/migrations/20250725154928_timestamp_with_timezone/migration.sql diff --git a/packages/hoppscotch-backend/package.json b/packages/hoppscotch-backend/package.json index 99f0f22f..42b01cd0 100644 --- a/packages/hoppscotch-backend/package.json +++ b/packages/hoppscotch-backend/package.json @@ -60,7 +60,6 @@ "graphql-subscriptions": "3.0.0", "handlebars": "4.7.8", "io-ts": "2.2.22", - "luxon": "3.7.1", "morgan": "1.10.1", "nodemailer": "7.0.5", "passport": "0.7.0", @@ -86,7 +85,6 @@ "@types/cookie-parser": "1.4.9", "@types/express": "5.0.3", "@types/jest": "30.0.0", - "@types/luxon": "3.6.2", "@types/node": "24.1.0", "@types/nodemailer": "6.4.17", "@types/passport-github2": "1.2.9", diff --git a/packages/hoppscotch-backend/prisma/migrations/20250725154928_timestamp_with_timezone/migration.sql b/packages/hoppscotch-backend/prisma/migrations/20250725154928_timestamp_with_timezone/migration.sql new file mode 100644 index 00000000..6078978d --- /dev/null +++ b/packages/hoppscotch-backend/prisma/migrations/20250725154928_timestamp_with_timezone/migration.sql @@ -0,0 +1,53 @@ +-- AlterTable +ALTER TABLE "Account" ALTER COLUMN "loggedIn" SET DATA TYPE TIMESTAMPTZ(3) USING "loggedIn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "InfraConfig" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "InfraToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC', +ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "InvitedUsers" ALTER COLUMN "invitedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "invitedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "PersonalAccessToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC', +ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "Shortcode" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "TeamCollection" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "TeamRequest" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "lastLoggedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "lastLoggedOn" AT TIME ZONE 'UTC', +ALTER COLUMN "lastActiveOn" SET DATA TYPE TIMESTAMPTZ(3) USING "lastActiveOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "UserCollection" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "UserHistory" ALTER COLUMN "executedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "executedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "UserRequest" ALTER COLUMN "createdOn" SET DATA TYPE TIMESTAMPTZ(3) USING "createdOn" AT TIME ZONE 'UTC', +ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "UserSettings" ALTER COLUMN "updatedOn" SET DATA TYPE TIMESTAMPTZ(3) USING "updatedOn" AT TIME ZONE 'UTC'; + +-- AlterTable +ALTER TABLE "VerificationToken" ALTER COLUMN "expiresOn" SET DATA TYPE TIMESTAMPTZ(3) USING "expiresOn" AT TIME ZONE 'UTC'; diff --git a/packages/hoppscotch-backend/prisma/migrations/migration_lock.toml b/packages/hoppscotch-backend/prisma/migrations/migration_lock.toml index fbffa92c..044d57cd 100644 --- a/packages/hoppscotch-backend/prisma/migrations/migration_lock.toml +++ b/packages/hoppscotch-backend/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file +# It should be added in your version-control system (e.g., Git) +provider = "postgresql" diff --git a/packages/hoppscotch-backend/prisma/schema.prisma b/packages/hoppscotch-backend/prisma/schema.prisma index 5d0a0f50..6a29be10 100644 --- a/packages/hoppscotch-backend/prisma/schema.prisma +++ b/packages/hoppscotch-backend/prisma/schema.prisma @@ -51,8 +51,8 @@ model TeamCollection { team Team @relation(fields: [teamID], references: [id], onDelete: Cascade) title String orderIndex Int - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model TeamRequest { @@ -64,8 +64,8 @@ model TeamRequest { title String request Json orderIndex Int - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model Shortcode { @@ -74,8 +74,8 @@ model Shortcode { embedProperties Json? creatorUid String? User User? @relation(fields: [creatorUid], references: [uid]) - createdOn DateTime @default(now()) - updatedOn DateTime @default(now()) @updatedAt + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @default(now()) @updatedAt @db.Timestamptz(3) @@unique(fields: [id, creatorUid], name: "creator_uid_shortcode_unique") } @@ -104,9 +104,9 @@ model User { userRequests UserRequest[] currentRESTSession Json? currentGQLSession Json? - lastLoggedOn DateTime? @db.Timestamp(3) - lastActiveOn DateTime? @db.Timestamp(3) - createdOn DateTime @default(now()) @db.Timestamp(3) + lastLoggedOn DateTime? @db.Timestamptz(3) + lastActiveOn DateTime? @db.Timestamptz(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) invitedUsers InvitedUsers[] shortcodes Shortcode[] personalAccessTokens PersonalAccessToken[] @@ -121,7 +121,7 @@ model Account { providerRefreshToken String? providerAccessToken String? providerScope String? - loggedIn DateTime @default(now()) @db.Timestamp(3) + loggedIn DateTime @default(now()) @db.Timestamptz(3) @@unique(fields: [provider, providerAccountId], name: "verifyProviderAccount") } @@ -131,7 +131,7 @@ model VerificationToken { token String @unique @default(cuid()) userUid String user User @relation(fields: [userUid], references: [uid], onDelete: Cascade) - expiresOn DateTime @db.Timestamp(3) + expiresOn DateTime @db.Timestamptz(3) @@unique(fields: [deviceIdentifier, token], name: "passwordless_deviceIdentifier_tokens") } @@ -141,7 +141,7 @@ model UserSettings { userUid String @unique user User @relation(fields: [userUid], references: [uid], onDelete: Cascade) properties Json - updatedOn DateTime @updatedAt @db.Timestamp(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model UserHistory { @@ -152,7 +152,7 @@ model UserHistory { request Json responseMetadata Json isStarred Boolean - executedOn DateTime @default(now()) @db.Timestamp(3) + executedOn DateTime @default(now()) @db.Timestamptz(3) } enum ReqType { @@ -174,7 +174,7 @@ model InvitedUsers { user User @relation(fields: [adminUid], references: [uid], onDelete: Cascade) adminEmail String inviteeEmail String @unique - invitedOn DateTime @default(now()) @db.Timestamp(3) + invitedOn DateTime @default(now()) @db.Timestamptz(3) } model UserRequest { @@ -187,8 +187,8 @@ model UserRequest { request Json type ReqType orderIndex Int - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model UserCollection { @@ -203,8 +203,8 @@ model UserCollection { data Json? orderIndex Int type ReqType - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } enum TeamAccessRole { @@ -217,10 +217,10 @@ model InfraConfig { id String @id @default(cuid()) name String @unique value String? - lastSyncedEnvFileValue String? + lastSyncedEnvFileValue String? // deprecated, use `value` instead isEncrypted Boolean @default(false) // Use case: Let's say, Admin wants to store a Secret Key, but doesn't want to store it in plain text in `value` column - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model PersonalAccessToken { @@ -229,9 +229,9 @@ model PersonalAccessToken { user User @relation(fields: [userUid], references: [uid], onDelete: Cascade) label String token String @unique @default(uuid()) - expiresOn DateTime? @db.Timestamp(3) - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @updatedAt @db.Timestamp(3) + expiresOn DateTime? @db.Timestamptz(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @updatedAt @db.Timestamptz(3) } model InfraToken { @@ -239,7 +239,7 @@ model InfraToken { creatorUid String label String token String @unique @default(uuid()) - expiresOn DateTime? @db.Timestamp(3) - createdOn DateTime @default(now()) @db.Timestamp(3) - updatedOn DateTime @default(now()) @db.Timestamp(3) + expiresOn DateTime? @db.Timestamptz(3) + createdOn DateTime @default(now()) @db.Timestamptz(3) + updatedOn DateTime @default(now()) @db.Timestamptz(3) } diff --git a/packages/hoppscotch-backend/src/auth/auth.service.ts b/packages/hoppscotch-backend/src/auth/auth.service.ts index 41109d8b..3d4da286 100644 --- a/packages/hoppscotch-backend/src/auth/auth.service.ts +++ b/packages/hoppscotch-backend/src/auth/auth.service.ts @@ -3,7 +3,6 @@ import { MailerService } from 'src/mailer/mailer.service'; import { PrismaService } from 'src/prisma/prisma.service'; import { UserService } from 'src/user/user.service'; import { VerifyMagicDto } from './dto/verify-magic.dto'; -import { DateTime } from 'luxon'; import * as argon2 from 'argon2'; import * as bcrypt from 'bcrypt'; import * as O from 'fp-ts/Option'; @@ -52,14 +51,15 @@ export class AuthService { const salt = await bcrypt.genSalt( parseInt(this.configService.get('INFRA.TOKEN_SALT_COMPLEXITY')), ); - const expiresOn = DateTime.now() - .plus({ - hours: parseInt( - this.configService.get('INFRA.MAGIC_LINK_TOKEN_VALIDITY'), - ), - }) - .toISO() - .toString(); + + // Calculate expiration time by adding hours to current time + let validityInHours = parseInt( + this.configService.get('INFRA.MAGIC_LINK_TOKEN_VALIDITY'), + ); + if (isNaN(validityInHours)) validityInHours = 24; // Default: 24 hours + + const expiresOn = new Date(); + expiresOn.setHours(expiresOn.getHours() + validityInHours); const idToken = await this.prisma.verificationToken.create({ data: { @@ -296,8 +296,8 @@ export class AuthService { ); } - const currentTime = DateTime.now().toISO(); - if (currentTime > passwordlessTokens.value.expiresOn.toISOString()) + const currentTime = new Date(); + if (currentTime > passwordlessTokens.value.expiresOn) return E.left({ message: MAGIC_LINK_EXPIRED, statusCode: HttpStatus.UNAUTHORIZED, diff --git a/packages/hoppscotch-backend/src/auth/helper.ts b/packages/hoppscotch-backend/src/auth/helper.ts index d76207ef..c417fb26 100644 --- a/packages/hoppscotch-backend/src/auth/helper.ts +++ b/packages/hoppscotch-backend/src/auth/helper.ts @@ -1,5 +1,4 @@ import { HttpException, HttpStatus } from '@nestjs/common'; -import { DateTime } from 'luxon'; import { AuthTokens } from 'src/types/AuthTokens'; import { Response } from 'express'; import * as cookie from 'cookie'; @@ -43,29 +42,29 @@ export const authCookieHandler = ( redirectUrl: string | null, configService: ConfigService, ) => { - const currentTime = DateTime.now(); - const accessTokenValidity = currentTime - .plus({ - milliseconds: parseInt(configService.get('INFRA.ACCESS_TOKEN_VALIDITY')), - }) - .toMillis(); - const refreshTokenValidity = currentTime - .plus({ - milliseconds: parseInt(configService.get('INFRA.REFRESH_TOKEN_VALIDITY')), - }) - .toMillis(); + // Calculate token validity periods in milliseconds + let accessTokenValidityInMs = parseInt( + configService.get('INFRA.ACCESS_TOKEN_VALIDITY'), + ); + let refreshTokenValidityInMs = parseInt( + configService.get('INFRA.REFRESH_TOKEN_VALIDITY'), + ); + + // Set default values if parsing results in NaN + if (isNaN(accessTokenValidityInMs)) accessTokenValidityInMs = 86400000; // Default: 1 day + if (isNaN(refreshTokenValidityInMs)) refreshTokenValidityInMs = 604800000; // Default: 7 days res.cookie(AuthTokenType.ACCESS_TOKEN, authTokens.access_token, { httpOnly: true, secure: configService.get('INFRA.ALLOW_SECURE_COOKIES') === 'true', sameSite: 'lax', - maxAge: accessTokenValidity, + maxAge: Date.now() + accessTokenValidityInMs, }); res.cookie(AuthTokenType.REFRESH_TOKEN, authTokens.refresh_token, { httpOnly: true, secure: configService.get('INFRA.ALLOW_SECURE_COOKIES') === 'true', sameSite: 'lax', - maxAge: refreshTokenValidity, + maxAge: Date.now() + refreshTokenValidityInMs, }); if (!redirect) { diff --git a/packages/hoppscotch-backend/src/auth/strategies/microsoft.strategy.ts b/packages/hoppscotch-backend/src/auth/strategies/microsoft.strategy.ts index 528fb9b2..885542df 100644 --- a/packages/hoppscotch-backend/src/auth/strategies/microsoft.strategy.ts +++ b/packages/hoppscotch-backend/src/auth/strategies/microsoft.strategy.ts @@ -26,12 +26,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy) { }); } - async validate( - accessToken: string, - refreshToken: string, - profile, - done, - ) { + async validate(accessToken: string, refreshToken: string, profile, done) { const email = profile?.emails?.[0]?.value; if (!validateEmail(email)) diff --git a/packages/hoppscotch-backend/src/guards/infra-token.guard.ts b/packages/hoppscotch-backend/src/guards/infra-token.guard.ts index e627b3fc..f2e7c5c2 100644 --- a/packages/hoppscotch-backend/src/guards/infra-token.guard.ts +++ b/packages/hoppscotch-backend/src/guards/infra-token.guard.ts @@ -5,7 +5,6 @@ import { UnauthorizedException, } from '@nestjs/common'; import { PrismaService } from 'src/prisma/prisma.service'; -import { DateTime } from 'luxon'; import { INFRA_TOKEN_EXPIRED, INFRA_TOKEN_HEADER_MISSING, @@ -37,8 +36,8 @@ export class InfraTokenGuard implements CanActivate { if (infraToken === null) throw new UnauthorizedException(INFRA_TOKEN_INVALID_TOKEN); - const currentTime = DateTime.now().toISO(); - if (currentTime > infraToken.expiresOn?.toISOString()) { + // Check if token has expired (if expiresOn is set) + if (infraToken.expiresOn && new Date() > infraToken.expiresOn) { throw new UnauthorizedException(INFRA_TOKEN_EXPIRED); } diff --git a/packages/hoppscotch-backend/src/guards/rest-pat-auth.guard.ts b/packages/hoppscotch-backend/src/guards/rest-pat-auth.guard.ts index d4f6d900..199943d3 100644 --- a/packages/hoppscotch-backend/src/guards/rest-pat-auth.guard.ts +++ b/packages/hoppscotch-backend/src/guards/rest-pat-auth.guard.ts @@ -7,7 +7,6 @@ import { import { Request } from 'express'; import { AccessTokenService } from 'src/access-token/access-token.service'; import * as E from 'fp-ts/Either'; -import { DateTime } from 'luxon'; import { ACCESS_TOKEN_EXPIRED, ACCESS_TOKEN_INVALID } from 'src/errors'; import { createCLIErrorResponse } from 'src/access-token/helper'; @Injectable() @@ -28,15 +27,23 @@ export class PATAuthGuard implements CanActivate { throw new BadRequestException( createCLIErrorResponse(ACCESS_TOKEN_INVALID), ); + request.user = userAccessToken.right.user; - const accessToken = userAccessToken.right; - if (accessToken.expiresOn === null) return true; - const today = DateTime.now().toISO(); - if (accessToken.expiresOn.toISOString() > today) return true; + // If token has no expiration, it's valid + if (accessToken.expiresOn === null) { + return true; + } - throw new BadRequestException(createCLIErrorResponse(ACCESS_TOKEN_EXPIRED)); + // Check if token has expired + if (new Date() > accessToken.expiresOn) { + throw new BadRequestException( + createCLIErrorResponse(ACCESS_TOKEN_EXPIRED), + ); + } + + return true; } private extractTokenFromHeader(request: Request): string | undefined { diff --git a/packages/hoppscotch-backend/src/mailer/templates/team-invitation.hbs b/packages/hoppscotch-backend/src/mailer/templates/team-invitation.hbs index 32032b45..17133ad6 100644 --- a/packages/hoppscotch-backend/src/mailer/templates/team-invitation.hbs +++ b/packages/hoppscotch-backend/src/mailer/templates/team-invitation.hbs @@ -511,7 +511,7 @@ diff --git a/packages/hoppscotch-backend/src/mailer/templates/user-invitation.hbs b/packages/hoppscotch-backend/src/mailer/templates/user-invitation.hbs index 3505f2ee..80ae7025 100644 --- a/packages/hoppscotch-backend/src/mailer/templates/user-invitation.hbs +++ b/packages/hoppscotch-backend/src/mailer/templates/user-invitation.hbs @@ -517,7 +517,7 @@ diff --git a/packages/hoppscotch-backend/src/utils.ts b/packages/hoppscotch-backend/src/utils.ts index cb3c3c09..9ccf1f88 100644 --- a/packages/hoppscotch-backend/src/utils.ts +++ b/packages/hoppscotch-backend/src/utils.ts @@ -266,12 +266,12 @@ export function escapeSqlLikeString(str: string) { /** * Calculate the expiration date of the token * - * @param expiresOn Number of days the token is valid for + * @param expiresInDays Number of days the token is valid for * @returns Date object of the expiration date */ -export function calculateExpirationDate(expiresOn: null | number) { - if (expiresOn === null) return null; - return new Date(Date.now() + expiresOn * 24 * 60 * 60 * 1000); +export function calculateExpirationDate(expiresInDays: null | number) { + if (expiresInDays === null) return null; + return new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1000); } /* diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5bf1997f..0fbf33c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -241,9 +241,6 @@ importers: io-ts: specifier: 2.2.22 version: 2.2.22(fp-ts@2.16.10) - luxon: - specifier: 3.7.1 - version: 3.7.1 morgan: specifier: 1.10.1 version: 1.10.1 @@ -314,9 +311,6 @@ importers: '@types/jest': specifier: 30.0.0 version: 30.0.0 - '@types/luxon': - specifier: 3.6.2 - version: 3.6.2 '@types/node': specifier: 24.1.0 version: 24.1.0 @@ -10917,10 +10911,6 @@ packages: resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==} engines: {node: '>=12'} - luxon@3.7.1: - resolution: {integrity: sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==} - engines: {node: '>=12'} - magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} @@ -26933,8 +26923,6 @@ snapshots: luxon@3.6.1: {} - luxon@3.7.1: {} - magic-string@0.25.9: dependencies: sourcemap-codec: 1.4.8