diff --git a/apps/partner-sas/package.json b/apps/partner-sas/package.json index 6f8a30de5..0fe261424 100644 --- a/apps/partner-sas/package.json +++ b/apps/partner-sas/package.json @@ -16,7 +16,8 @@ "test:e2e": "playwright test", "test:e2e:ui": "playwright test --ui", "test:e2e:debug": "playwright test --debug", - "include:shared": "jiti ../../scripts/copyFiles.ts ../../shared/ public/_static/shared" + "include:shared": "jiti ../../scripts/copyFiles.ts ../../shared/ public/_static/shared", + "format": "prettier --write ." }, "dependencies": { "@formatjs/intl": "^3.1.6", diff --git a/apps/partner-sas/prettier.config.cjs b/apps/partner-sas/prettier.config.cjs deleted file mode 100644 index 2fd3b38fe..000000000 --- a/apps/partner-sas/prettier.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - semi: false, - trailingComma: "es5", - singleQuote: false, - printWidth: 80, - tabWidth: 2, - endOfLine: "lf", -} diff --git a/apps/partner-sas/prettier.config.js b/apps/partner-sas/prettier.config.js new file mode 100644 index 000000000..8d41cc176 --- /dev/null +++ b/apps/partner-sas/prettier.config.js @@ -0,0 +1,14 @@ +/** + * @see https://prettier.io/docs/configuration + * @type {import("prettier").Config} + */ +const config = { + semi: false, + trailingComma: "es5", + singleQuote: false, + printWidth: 80, + tabWidth: 2, + endOfLine: "lf", +} + +export default config diff --git a/apps/redis-api/docker-compose.yaml b/apps/redis-api/docker-compose.yaml index a650b3a62..2a8d67e44 100644 --- a/apps/redis-api/docker-compose.yaml +++ b/apps/redis-api/docker-compose.yaml @@ -1,27 +1,27 @@ services: - redis-api: - build: - context: . - dockerfile: Dockerfile - ports: - - "3101:3001" - depends_on: - - redis - environment: - - REDIS_CONNECTION=redis:6379 - - PRIMARY_API_KEY= - - SECONDARY_API_KEY= - - NODE_ENV=development - - SENTRY_ENABLED=false + redis-api: + build: + context: . + dockerfile: Dockerfile + ports: + - "3101:3001" + depends_on: + - redis + environment: + - REDIS_CONNECTION=redis:6379 + - PRIMARY_API_KEY= + - SECONDARY_API_KEY= + - NODE_ENV=development + - SENTRY_ENABLED=false - redis: - image: redis:6 - ports: - - "6379:6379" + redis: + image: redis:6 + ports: + - "6379:6379" - redisinsight: - image: redis/redisinsight:latest - ports: - - "5540:5540" - depends_on: - - redis + redisinsight: + image: redis/redisinsight:latest + ports: + - "5540:5540" + depends_on: + - redis diff --git a/apps/redis-api/package.json b/apps/redis-api/package.json index 55988defb..0f8b07dac 100644 --- a/apps/redis-api/package.json +++ b/apps/redis-api/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "bun --watch src/index.ts | pino-pretty -o '{if module}[{module}] {end}{msg}' -i pid,hostname", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && tsc", - "lint:fix": "eslint . --ext ts,tsx --fix --report-unused-disable-directives --max-warnings 0 && tsc" + "lint:fix": "eslint . --ext ts,tsx --fix --report-unused-disable-directives --max-warnings 0 && tsc", + "format": "prettier --write ." }, "dependencies": { "@elysiajs/server-timing": "^1.3.0", @@ -28,7 +29,6 @@ "eslint": "^9", "eslint-plugin-simple-import-sort": "^10.0.0", "pino-pretty": "^13.0.0", - "prettier": "^3.5.3", "typescript": "^5.7.2" }, "prettier": { diff --git a/apps/redis-api/src/services/redis/queueDelete.ts b/apps/redis-api/src/services/redis/queueDelete.ts index d2bb784d3..c129d6e00 100644 --- a/apps/redis-api/src/services/redis/queueDelete.ts +++ b/apps/redis-api/src/services/redis/queueDelete.ts @@ -1,4 +1,4 @@ -import { Queue,Worker } from "bullmq"; +import { Queue, Worker } from "bullmq"; import z from "zod"; import { env } from "@/env"; @@ -6,7 +6,7 @@ import { sentry } from "@/server/sentry.server.config"; import { loggerModule } from "@/utils/logger"; import { timeout } from "@/utils/timeout"; -import { bullmqredis,redis } from "."; +import { bullmqredis, redis } from "."; const DELETE_JOB = "deleteQueueJob"; const deleteQueueLogger = loggerModule("deleteQueue"); diff --git a/apps/redis-api/src/utils/mask.ts b/apps/redis-api/src/utils/mask.ts index 971583a37..a0148f5fb 100644 --- a/apps/redis-api/src/utils/mask.ts +++ b/apps/redis-api/src/utils/mask.ts @@ -8,35 +8,39 @@ */ const maskChar = "*"; export function mask( - value: string, - options?: { visibleStart?: number; visibleEnd?: number; maxLength?: number }, + value: string, + options?: { + visibleStart?: number; + visibleEnd?: number; + maxLength?: number; + }, ): string { - if (!value) return ""; + if (!value) return ""; - const { visibleStart = 2, visibleEnd = 2, maxLength = 10 } = options ?? {}; + const { visibleStart = 2, visibleEnd = 2, maxLength = 10 } = options ?? {}; - if (isEmail(value)) { - return maskEmail(value); - } + if (isEmail(value)) { + return maskEmail(value); + } - const totalVisible = visibleStart + visibleEnd; - if (value.length <= totalVisible) { - return maskChar.repeat(value.length); - } + const totalVisible = visibleStart + visibleEnd; + if (value.length <= totalVisible) { + return maskChar.repeat(value.length); + } - const start = value.slice(0, visibleStart); - const middle = value.slice(visibleStart, -visibleEnd || undefined); - const end = visibleEnd ? value.slice(-visibleEnd) : ""; + const start = value.slice(0, visibleStart); + const middle = value.slice(visibleStart, -visibleEnd || undefined); + const end = visibleEnd ? value.slice(-visibleEnd) : ""; - const maskedLength = Math.min(middle.length, maxLength); - return start + maskChar.repeat(maskedLength) + end; + const maskedLength = Math.min(middle.length, maxLength); + return start + maskChar.repeat(maskedLength) + end; } function maskEmail(email: string): string { - const [local, domain] = email.split("@"); - if (!domain || !local) return mask(email); - const [subDomain, tld] = domain.split(/\.(?=[^.]+$)/); - return `${mask(local)}@${mask(subDomain ?? "")}.${tld}`; + const [local, domain] = email.split("@"); + if (!domain || !local) return mask(email); + const [subDomain, tld] = domain.split(/\.(?=[^.]+$)/); + return `${mask(local)}@${mask(subDomain ?? "")}.${tld}`; } const isEmail = (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value); diff --git a/apps/redis-api/tsconfig.json b/apps/redis-api/tsconfig.json index db662480b..0dd63b5d5 100644 --- a/apps/redis-api/tsconfig.json +++ b/apps/redis-api/tsconfig.json @@ -1,8 +1,8 @@ { - "extends": "@scandic-hotels/typescript-config/bun.json", - "compilerOptions": { - "paths": { - "@/*": ["./src/*"] + "extends": "@scandic-hotels/typescript-config/bun.json", + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } } - } } diff --git a/apps/scandic-redirect/.prettierignore b/apps/scandic-redirect/.prettierignore new file mode 100644 index 000000000..02a02e6b5 --- /dev/null +++ b/apps/scandic-redirect/.prettierignore @@ -0,0 +1 @@ +netlify/functions/data/*.json \ No newline at end of file diff --git a/apps/scandic-redirect/README.md b/apps/scandic-redirect/README.md index eedd4bae9..73fbf70f3 100644 --- a/apps/scandic-redirect/README.md +++ b/apps/scandic-redirect/README.md @@ -16,10 +16,10 @@ https://scandichotelsab.sharepoint.com/:x:/s/921-ContentNewweb/ETGStOQAARtJhJXG9 - Open it - Each domain/language has its own sheet - Export each sheet into their respective language code - - File > Export > Download as CSV UTF-8 - - Save as [lang].csv in `./scripts/data/csv` folder + - File > Export > Download as CSV UTF-8 + - Save as [lang].csv in `./scripts/data/csv` folder - Run the `generate` script target - - E.g. `yarn workspace @scandic-hotels/scandic-redirect generate` + - E.g. `yarn workspace @scandic-hotels/scandic-redirect generate` - Commit and push the JSON files in `./netlify/functions/data`. - Create a PR - Profit! diff --git a/apps/scandic-redirect/netlify/functions/redirect.mts b/apps/scandic-redirect/netlify/functions/redirect.mts index 160202846..1fd5b8809 100644 --- a/apps/scandic-redirect/netlify/functions/redirect.mts +++ b/apps/scandic-redirect/netlify/functions/redirect.mts @@ -1,12 +1,12 @@ -import { createReadStream } from "fs"; -import { join } from "path"; +import { createReadStream } from "fs" +import { join } from "path" export default async (req: Request) => { try { - const body = await req.json(); + const body = await req.json() if (body.lang && body.pathname) { - const filePath = join(import.meta.dirname, `./data/${body.lang}.json`); + const filePath = join(import.meta.dirname, `./data/${body.lang}.json`) const redirectUrl = await new Promise( (resolve, reject) => { @@ -14,58 +14,58 @@ export default async (req: Request) => { emitClose: false, encoding: "utf-8", highWaterMark: 1024, - }); - const data: string[] = []; + }) + const data: string[] = [] stream.on("data", (chunk) => { if (data.length === 3) { - data.shift(); + data.shift() } - data.push(chunk.toString()); + data.push(chunk.toString()) // Since we strip trailing slash (in the trailingSlash middleware) before entering this middleware, // we need check matching paths both including and excluding trailing slash. - const re = new RegExp(`"${body.pathname}\/?":"([^"]+)"`); + const re = new RegExp(`"${body.pathname}\/?":"([^"]+)"`) - const match = data.join("").match(re); + const match = data.join("").match(re) if (match?.[1]) { - stream.destroy(); - resolve(match[1]); + stream.destroy() + resolve(match[1]) } - }); + }) stream.on("error", (err) => { - console.error("Stream error:", err); - stream.destroy(); - reject(err); - }); + console.error("Stream error:", err) + stream.destroy() + reject(err) + }) stream.on("end", () => { - stream.destroy(); - resolve(null); // No match found - }); + stream.destroy() + resolve(null) // No match found + }) } - ); + ) if (redirectUrl) { // Make sure to exclude trailing slash in the redirectUrl to avoid an extra middleware roundtrip const redirectUrlWithoutTrailingSlash = redirectUrl.endsWith("/") ? redirectUrl.slice(0, -1) - : redirectUrl; + : redirectUrl if (redirectUrlWithoutTrailingSlash === body.pathname) { console.log( `[scandic-redirect] recieved ${body.pathname}, found ${redirectUrlWithoutTrailingSlash}, no-op` - ); - return new Response("Not Found", { status: 404 }); + ) + return new Response("Not Found", { status: 404 }) } console.log( `[scandic-redirect] recieved ${body.pathname}, return ${redirectUrlWithoutTrailingSlash}, success` - ); - return new Response(redirectUrlWithoutTrailingSlash); + ) + return new Response(redirectUrlWithoutTrailingSlash) } } - console.log(`[scandic-redirect] recieved ${body.pathname}, not found`); - return new Response("Not Found", { status: 404 }); + console.log(`[scandic-redirect] recieved ${body.pathname}, not found`) + return new Response("Not Found", { status: 404 }) } catch (error) { - return new Response("Bad request", { status: 400 }); + return new Response("Bad request", { status: 400 }) } -}; +} diff --git a/apps/scandic-redirect/package.json b/apps/scandic-redirect/package.json index a1c298905..0574ba8ad 100644 --- a/apps/scandic-redirect/package.json +++ b/apps/scandic-redirect/package.json @@ -1,27 +1,28 @@ { - "name": "@scandic-hotels/scandic-redirect", - "version": "0.1.0", - "private": true, - "packageManager": "yarn@4.6.0", - "scripts": { - "test": "vitest run", - "test:watch": "vitest", - "generate": "jiti ./scripts/generateRedirectFile/index.ts" - }, - "dependencies": { - "@netlify/functions": "^3.0.0" - }, - "devDependencies": { - "convert-csv-to-json": "^3.4.0", - "jiti": "^2.6.1", - "vitest": "^3.2.4" - }, - "prettier": { - "semi": false, - "trailingComma": "es5", - "singleQuote": false, - "printWidth": 80, - "tabWidth": 2, - "endOfLine": "lf" - } + "name": "@scandic-hotels/scandic-redirect", + "version": "0.1.0", + "private": true, + "packageManager": "yarn@4.6.0", + "scripts": { + "test": "vitest run", + "test:watch": "vitest", + "generate": "jiti ./scripts/generateRedirectFile/index.ts", + "format": "prettier --write ." + }, + "dependencies": { + "@netlify/functions": "^3.0.0" + }, + "devDependencies": { + "convert-csv-to-json": "^3.4.0", + "jiti": "^2.6.1", + "vitest": "^3.2.4" + }, + "prettier": { + "semi": false, + "trailingComma": "es5", + "singleQuote": false, + "printWidth": 80, + "tabWidth": 2, + "endOfLine": "lf" + } } diff --git a/apps/scandic-web/app/[lang]/(live)/middleware-error/[status]/page.tsx b/apps/scandic-web/app/[lang]/(live)/middleware-error/[status]/page.tsx index 6bcefcd30..49e5f347c 100644 --- a/apps/scandic-web/app/[lang]/(live)/middleware-error/[status]/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/middleware-error/[status]/page.tsx @@ -2,11 +2,14 @@ import styles from "./page.module.css" import type { LangParams, LayoutArgs, StatusParams } from "@/types/params" -export default async function MiddlewareError(props: LayoutArgs) { - const params = await props.params; +export default async function MiddlewareError( + props: LayoutArgs +) { + const params = await props.params return ( // eslint-disable-next-line formatjs/no-literal-string-in-jsx -
Middleware error {params.lang} {params.status} +
+ Middleware error {params.lang} {params.status}
- ); + ) } diff --git a/apps/scandic-web/app/[lang]/(no-layout)/hotelreservation/my-stay/receipt/page.tsx b/apps/scandic-web/app/[lang]/(no-layout)/hotelreservation/my-stay/receipt/page.tsx index 6d931f287..24e10d694 100644 --- a/apps/scandic-web/app/[lang]/(no-layout)/hotelreservation/my-stay/receipt/page.tsx +++ b/apps/scandic-web/app/[lang]/(no-layout)/hotelreservation/my-stay/receipt/page.tsx @@ -6,8 +6,10 @@ import { Receipt } from "@/components/HotelReservation/MyStay/Receipt" import type { LangParams, PageArgs } from "@/types/params" -export default async function ReceiptPage(props: PageArgs) { - const searchParams = await props.searchParams; +export default async function ReceiptPage( + props: PageArgs +) { + const searchParams = await props.searchParams if (!searchParams.RefId) { notFound() } diff --git a/apps/scandic-web/components/Blocks/CampaignHotelListing/index.tsx b/apps/scandic-web/components/Blocks/CampaignHotelListing/index.tsx index 15be4a088..dbe420ae2 100644 --- a/apps/scandic-web/components/Blocks/CampaignHotelListing/index.tsx +++ b/apps/scandic-web/components/Blocks/CampaignHotelListing/index.tsx @@ -54,7 +54,7 @@ export default async function CampaignHotelListing({ { label: intl.formatMessage({ id: "common.tripAdvisorRating", - defaultMessage: "TripAdvisor rating", + defaultMessage: "Tripadvisor rating", }), value: HotelSortOption.TripAdvisorRating, }, diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Points/EarnAndBurn/JourneyTable/ClientTable/Row/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/Points/EarnAndBurn/JourneyTable/ClientTable/Row/index.tsx index e6536e22e..eed37d83d 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Points/EarnAndBurn/JourneyTable/ClientTable/Row/index.tsx +++ b/apps/scandic-web/components/Blocks/DynamicContent/Points/EarnAndBurn/JourneyTable/ClientTable/Row/index.tsx @@ -37,7 +37,7 @@ export default function Row({ transaction }: RowProps) { transaction.nights === 0 ? intl.formatMessage({ id: "earnAndBurn.journeyTable.pointsActivity", - defaultMessage: "Points activity", + defaultMessage: "Point activity", }) : transaction.hotelName && transaction.city ? `${transaction.hotelName}, ${transaction.city} ${nightsMsg}` diff --git a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx index a8819e50b..b7d33561d 100644 --- a/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx +++ b/apps/scandic-web/components/ContentType/DestinationPage/DestinationCityPage/index.tsx @@ -85,7 +85,7 @@ export default async function DestinationCityPage({ { label: intl.formatMessage({ id: "common.tripAdvisorRating", - defaultMessage: "TripAdvisor rating", + defaultMessage: "Tripadvisor rating", }), value: HotelSortOption.TripAdvisorRating, }, diff --git a/apps/scandic-web/components/HotelReservation/MyStay/GuestDetails/index.tsx b/apps/scandic-web/components/HotelReservation/MyStay/GuestDetails/index.tsx index 374fd3e9e..3125839f7 100644 --- a/apps/scandic-web/components/HotelReservation/MyStay/GuestDetails/index.tsx +++ b/apps/scandic-web/components/HotelReservation/MyStay/GuestDetails/index.tsx @@ -235,7 +235,7 @@ export default function GuestDetails({ {intl.formatMessage({ id: "myStay.guestDetails.modifyGuestDetails", - defaultMessage: "Modify guest details", + defaultMessage: "Edit guest details", })} @@ -265,7 +265,7 @@ export default function GuestDetails({ {intl.formatMessage({ id: "myStay.guestDetails.modifyGuestDetails", - defaultMessage: "Modify guest details", + defaultMessage: "Edit guest details", })} @@ -280,7 +280,7 @@ export default function GuestDetails({ {({ close }) => ( @@ -288,7 +288,7 @@ export default function GuestDetails({ setIsModifyGuestDetailsOpen(false)} content={ diff --git a/apps/scandic-web/components/HotelReservation/MyStay/ReferenceCard/Actions/NotCancelled/ManageStay/Actions/GuaranteeLateArrival/Form/index.tsx b/apps/scandic-web/components/HotelReservation/MyStay/ReferenceCard/Actions/NotCancelled/ManageStay/Actions/GuaranteeLateArrival/Form/index.tsx index 27eb9401d..acc70df4b 100644 --- a/apps/scandic-web/components/HotelReservation/MyStay/ReferenceCard/Actions/NotCancelled/ManageStay/Actions/GuaranteeLateArrival/Form/index.tsx +++ b/apps/scandic-web/components/HotelReservation/MyStay/ReferenceCard/Actions/NotCancelled/ManageStay/Actions/GuaranteeLateArrival/Form/index.tsx @@ -120,7 +120,7 @@ export default function Form() { { id: "myStay.gla.termsAndConditionsMessage", defaultMessage: - "I accept the terms for this stay and the general Booking & Cancellation Terms, and understand Scandic will process my personal data for this stay in accordance with Scandic's Privacy Policy. ", + "I accept the terms for this stay and the general Booking & Cancellation Terms, and understand Scandic will process my personal data for this stay in accordance with Scandic's Privacy Policy.", }, { termsAndConditionsLink: (str) => ( diff --git a/apps/scandic-web/components/HotelReservation/MyStay/Rooms/MultiRoom/Room.tsx b/apps/scandic-web/components/HotelReservation/MyStay/Rooms/MultiRoom/Room.tsx index 17ba6b13f..4ff4281b6 100644 --- a/apps/scandic-web/components/HotelReservation/MyStay/Rooms/MultiRoom/Room.tsx +++ b/apps/scandic-web/components/HotelReservation/MyStay/Rooms/MultiRoom/Room.tsx @@ -301,7 +301,7 @@ export default function Room({ booking, roomNr, user }: RoomProps) {

{intl.formatMessage({ id: "myStay.modifyBy", - defaultMessage: "Modify By", + defaultMessage: "Modify by", })}

diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx b/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx index ae57ccb43..0324d2948 100644 --- a/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx @@ -36,7 +36,7 @@ export default async function LevelProgressCard({

{intl.formatMessage({ id: "myPages.yourLevelProgress", - defaultMessage: "Your Level Progress", + defaultMessage: "Your level progress", })}

diff --git a/apps/scandic-web/components/SidePeeks/BookedRoomSidePeekContent/index.tsx b/apps/scandic-web/components/SidePeeks/BookedRoomSidePeekContent/index.tsx index ebc1ac882..4441acd3d 100644 --- a/apps/scandic-web/components/SidePeeks/BookedRoomSidePeekContent/index.tsx +++ b/apps/scandic-web/components/SidePeeks/BookedRoomSidePeekContent/index.tsx @@ -293,7 +293,7 @@ export default function BookedRoomSidePeekContent({

{intl.formatMessage({ id: "myStay.modifyBy", - defaultMessage: "Modify By", + defaultMessage: "Modify by", })}

diff --git a/apps/scandic-web/components/TempDesignSystem/MeetingRoomCard/utils.ts b/apps/scandic-web/components/TempDesignSystem/MeetingRoomCard/utils.ts index 9c1ebb0dd..99fa345b9 100644 --- a/apps/scandic-web/components/TempDesignSystem/MeetingRoomCard/utils.ts +++ b/apps/scandic-web/components/TempDesignSystem/MeetingRoomCard/utils.ts @@ -85,7 +85,7 @@ export function translateSeatingType(type: string, intl: IntlShape) { case SeatingType.Theatre: return intl.formatMessage({ id: "meetingRoomCard.theatre", - defaultMessage: "Theatre", + defaultMessage: "Theater", }) case SeatingType.UShape: return intl.formatMessage({ diff --git a/apps/scandic-web/package.json b/apps/scandic-web/package.json index 0b15862d9..ac8b4cfd9 100644 --- a/apps/scandic-web/package.json +++ b/apps/scandic-web/package.json @@ -20,7 +20,8 @@ "ci:build": "yarn lint && yarn test && yarn build", "clean": "rm -rf .next", "check-types": "tsc --noEmit", - "include:shared": "jiti ../../scripts/copyFiles.ts ../../shared public/_static/shared" + "include:shared": "jiti ../../scripts/copyFiles.ts ../../shared public/_static/shared", + "format": "prettier --write ." }, "dependencies": { "@contentstack/live-preview-utils": "^3.2.1", @@ -127,7 +128,6 @@ "json-sort-cli": "^4.0.9", "lint-staged": "^15.5.2", "netlify-plugin-cypress": "^2.2.1", - "prettier": "^3.5.3", "schema-dts": "^1.1.5", "start-server-and-test": "^2.0.11", "ts-morph": "^25.0.1", diff --git a/apps/scandic-web/prettier.config.cjs b/apps/scandic-web/prettier.config.cjs deleted file mode 100644 index 2fd3b38fe..000000000 --- a/apps/scandic-web/prettier.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - semi: false, - trailingComma: "es5", - singleQuote: false, - printWidth: 80, - tabWidth: 2, - endOfLine: "lf", -} diff --git a/apps/scandic-web/prettier.config.js b/apps/scandic-web/prettier.config.js new file mode 100644 index 000000000..8d41cc176 --- /dev/null +++ b/apps/scandic-web/prettier.config.js @@ -0,0 +1,14 @@ +/** + * @see https://prettier.io/docs/configuration + * @type {import("prettier").Config} + */ +const config = { + semi: false, + trailingComma: "es5", + singleQuote: false, + printWidth: 80, + tabWidth: 2, + endOfLine: "lf", +} + +export default config diff --git a/package.json b/package.json index cedc1d3b9..26e6f28eb 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dev:ds": "turbo run dev --filter=@scandic-hotels/design-system --output-logs new-only", "dev:sas": "turbo run dev --filter=@scandic-hotels/partner-sas --output-logs new-only", "test": "turbo run test", + "format": "turbo run format", "postinstall": "husky", "icons:update": "jiti scripts/material-symbols-update.mts", "check-types": "turbo run check-types", @@ -25,7 +26,8 @@ "i18n:distribute": "jiti scripts/i18n/distribute.ts scandic-web partner-sas", "i18n:push": "yarn i18n:extract && yarn i18n:upload", "i18n:pull": "yarn i18n:download && yarn i18n:compile && yarn i18n:distribute", - "i18n:sync": "yarn i18n:push && yarn i18n:pull" + "i18n:sync": "yarn i18n:push && yarn i18n:pull", + "i18n:syncDefaultMessage": "yarn i18n:download && bun scripts/i18n/syncDefaultMessage/index.ts scripts/i18n/translations/en.json '{apps,packages}/**/*.{tsx,ts}' && yarn format --force" }, "workspaces": [ "apps/*", @@ -41,6 +43,7 @@ "husky": "^9.1.7", "jiti": "^1.21.0", "lint-staged": "^15.2.2", + "prettier": "^3.6.2", "ts-node": "^10.9.2", "turbo": "^2.5.2" }, diff --git a/packages/booking-flow/lib/components/BookingConfirmation/Promos/index.tsx b/packages/booking-flow/lib/components/BookingConfirmation/Promos/index.tsx index 2b65e0a1f..9ff38565d 100644 --- a/packages/booking-flow/lib/components/BookingConfirmation/Promos/index.tsx +++ b/packages/booking-flow/lib/components/BookingConfirmation/Promos/index.tsx @@ -38,7 +38,7 @@ export function Promos({ booking }: PromosProps) { {intl.formatMessage({ id: "breakfastAccordion.allDayBreakfast", - defaultMessage: "All-day breakfast", + defaultMessage: + "Grab our Brekkie Deal for 69 SEK – coffee & sandwich, available 6 AM–noon.", })}

diff --git a/packages/booking-flow/package.json b/packages/booking-flow/package.json index 44505aa41..5c418db09 100644 --- a/packages/booking-flow/package.json +++ b/packages/booking-flow/package.json @@ -8,7 +8,8 @@ "lint": "eslint . --max-warnings 0 && tsc --noEmit", "lint:fix": "eslint . --fix && tsc --noEmit", "test": "vitest run --passWithNoTests", - "test:watch": "vitest" + "test:watch": "vitest", + "format": "prettier --write ." }, "exports": { "./BookingFlowConfig": "./lib/bookingFlowConfig/bookingFlowConfig.tsx", diff --git a/packages/booking-flow/prettier.config.cjs b/packages/booking-flow/prettier.config.cjs deleted file mode 100644 index 2fd3b38fe..000000000 --- a/packages/booking-flow/prettier.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - semi: false, - trailingComma: "es5", - singleQuote: false, - printWidth: 80, - tabWidth: 2, - endOfLine: "lf", -} diff --git a/packages/booking-flow/prettier.config.js b/packages/booking-flow/prettier.config.js new file mode 100644 index 000000000..8d41cc176 --- /dev/null +++ b/packages/booking-flow/prettier.config.js @@ -0,0 +1,14 @@ +/** + * @see https://prettier.io/docs/configuration + * @type {import("prettier").Config} + */ +const config = { + semi: false, + trailingComma: "es5", + singleQuote: false, + printWidth: 80, + tabWidth: 2, + endOfLine: "lf", +} + +export default config diff --git a/packages/common/package.json b/packages/common/package.json index be057a73f..4bf2c3d43 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -8,7 +8,8 @@ "test": "vitest run", "test:watch": "vitest", "check-types": "tsc --noEmit", - "lint": "eslint . --max-warnings 0 && tsc --noEmit" + "lint": "eslint . --max-warnings 0 && tsc --noEmit", + "format": "prettier --write ." }, "exports": { "./polyfills": "./polyfills/index.ts", diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 5e273ab4e..6a38236b4 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -269,7 +269,6 @@ "lint-staged": "^15.5.2", "motion": "^12.10.0", "playwright": "^1.54.2", - "prettier": "^3.5.3", "react": "^19.1.0", "react-dom": "^19.1.0", "rollup": "^4.40.2", diff --git a/packages/tracking/package.json b/packages/tracking/package.json index 437b4e285..92ae5660a 100644 --- a/packages/tracking/package.json +++ b/packages/tracking/package.json @@ -8,7 +8,8 @@ "test": "vitest run", "test:watch": "vitest", "check-types": "tsc --noEmit", - "lint": "eslint . --max-warnings 0 && tsc --noEmit" + "lint": "eslint . --max-warnings 0 && tsc --noEmit", + "format": "prettier --write ." }, "exports": { "./*": "./lib/*.ts", diff --git a/packages/trpc/package.json b/packages/trpc/package.json index 585eea93e..e192f5cc6 100644 --- a/packages/trpc/package.json +++ b/packages/trpc/package.json @@ -8,7 +8,8 @@ "lint": "eslint . --max-warnings 0 && tsc --noEmit", "lint:fix": "eslint . --fix && tsc --noEmit", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "format": "prettier --write ." }, "exports": { ".": "./lib/index.ts", diff --git a/packages/trpc/prettier.config.cjs b/packages/trpc/prettier.config.cjs deleted file mode 100644 index b78e09189..000000000 --- a/packages/trpc/prettier.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - semi: false, - trailingComma: "es5", - singleQuote: false, - printWidth: 80, - tabWidth: 2, - endOfLine: "lf", -}; diff --git a/packages/trpc/prettier.config.js b/packages/trpc/prettier.config.js new file mode 100644 index 000000000..8d41cc176 --- /dev/null +++ b/packages/trpc/prettier.config.js @@ -0,0 +1,14 @@ +/** + * @see https://prettier.io/docs/configuration + * @type {import("prettier").Config} + */ +const config = { + semi: false, + trailingComma: "es5", + singleQuote: false, + printWidth: 80, + tabWidth: 2, + endOfLine: "lf", +} + +export default config diff --git a/scripts/i18n/syncDefaultMessage/index.ts b/scripts/i18n/syncDefaultMessage/index.ts index 16e646251..02361182c 100644 --- a/scripts/i18n/syncDefaultMessage/index.ts +++ b/scripts/i18n/syncDefaultMessage/index.ts @@ -31,8 +31,11 @@ Examples: const isDryRun = args.includes("--dry-run"); const globPattern = args[1]; // Find all component files - const componentFiles = glob.sync(globPattern); + const componentFiles = glob.sync(globPattern); + console.log( + `Found ${componentFiles.length} files to sync using ${globPattern}` + ); let filesUpdated = 0; for (const filePath of componentFiles) { diff --git a/scripts/i18n/syncDefaultMessage/syncFile.test.ts b/scripts/i18n/syncDefaultMessage/syncFile.test.ts index fa93fa1b9..93d4f98ef 100644 --- a/scripts/i18n/syncDefaultMessage/syncFile.test.ts +++ b/scripts/i18n/syncDefaultMessage/syncFile.test.ts @@ -74,9 +74,32 @@ describe("syncFile", () => { }); expect(fsMock.readFileSync).toHaveBeenCalledWith("file.ts", "utf-8"); - expect(fsMock.writeFileSync).toHaveBeenCalled(); + // expect(fsMock.writeFileSync).toHaveBeenCalled(); expect(result).toEqual(createMockComponent("myKey", "old message")); }); + + it("updates complex components with replacements", async () => { + const fsMock = (await import("fs")) as any; + + fsMock.existsSync.mockReturnValue(true); + fsMock.readFileSync.mockReturnValue( + createComplexMockComponent( + "complexKey", + "Yes, I accept the general Booking & Cancellation Terms, and understand that Scandic will process my personal data in accordance with Scandic's Privacy policy." + ) + ); + + const { syncFile } = await import("./syncFile"); + + const { fileContent: result } = syncFile({ + path: "file.ts", + translations: { complexKey: "replace this text" }, + }); + + expect(fsMock.readFileSync).toHaveBeenCalledWith("file.ts", "utf-8"); + // expect(fsMock.writeFileSync).toHaveBeenCalled(); + expect(result).toContain("replace this text"); + }); }); function createMockComponent(translationId: string, defaultMessage: string) { @@ -90,3 +113,25 @@ function createMockComponent(translationId: string, defaultMessage: string) { return
{message}
; }`; } + +function createComplexMockComponent( + translationId: string, + defaultMessage: string +) { + return `export function TestComponent() { + const intl = useIntl(); + return ( +
+ {intl.formatMessage( + { + id: "${translationId}", + defaultMessage: "${defaultMessage}", + }, + { + replacement: (str) => {str}, + } + )} +
+ ); +}`; +} diff --git a/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.test.ts b/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.test.ts index fe1330e15..989274b7f 100644 --- a/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.test.ts +++ b/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.test.ts @@ -99,4 +99,38 @@ describe("syncIntlFormatMessage", () => { fileContent, }); }); + + it("handles formatMessage with replacements", () => { + const fileContent = + 'intl.formatMessage({ id: "myKey", defaultMessage: "old message" }, { stuff: (str) => {str} } })'; + expect( + syncIntlFormatMessage({ + fileContent, + translations: { + myKey: "new message", + }, + }) + ).toEqual({ + updated: true, + fileContent: + 'intl.formatMessage({ id: "myKey", defaultMessage: "new message" }, { stuff: (str) => {str} } })', + }); + }); + + it("handles formatMessage with replacements", () => { + const fileContent = + 'intl.formatMessage({ id: "myKey", defaultMessage: "old message" }, { stuff: (str) => {str} } })'; + expect( + syncIntlFormatMessage({ + fileContent, + translations: { + myKey: "new message", + }, + }) + ).toEqual({ + updated: true, + fileContent: + 'intl.formatMessage({ id: "myKey", defaultMessage: "new message" }, { stuff: (str) => {str} } })', + }); + }); }); diff --git a/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.ts b/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.ts index 88f049b7d..83b77c542 100644 --- a/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.ts +++ b/scripts/i18n/syncDefaultMessage/syncIntlFormatMessage.ts @@ -11,15 +11,17 @@ export function syncIntlFormatMessage({ for (const [messageId, messageValue] of entries) { const escapedId = messageId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - // Find intl.formatMessage({...}) blocks that contain the specific id + // Find intl.formatMessage({...}) or intl.formatMessage({...}, secondArg) blocks that contain the specific id const outerRegex = new RegExp( - `intl\\.formatMessage\\(\\s*\\{([^}]*?\\bid\\s*:\\s*['"]${escapedId}['"][^}]*?)\\}\\s*\\)`, + // group 1 = inner object content (without surrounding braces) + // group 2 = optional second argument (anything until the closing parenthesis, non-greedy) + `intl\\.formatMessage\\(\\s*\\{([^}]*?\\bid\\s*:\\s*['"]${escapedId}['"][^}]*?)\\}\\s*(?:,\\s*([^)]*?))?\\s*\\)`, "gs" ); fileContent = fileContent.replace( outerRegex, - (fullMatch, innerObject) => { + (fullMatch: string, innerObject: string, secondArg?: string) => { // Find defaultMessage: '...' or "..." const dmRegex = /defaultMessage\s*:\s*(['"])((?:\\.|[\s\S])*?)\1/; @@ -38,7 +40,9 @@ export function syncIntlFormatMessage({ ); updated = true; - return `intl.formatMessage({${newInner}})`; + // Preserve secondArg if present + const secondArgPart = secondArg ? `, ${secondArg}` : ""; + return `intl.formatMessage({${newInner}}${secondArgPart})`; } ); } diff --git a/scripts/i18n/syncDefaultMessage/test.tsx b/scripts/i18n/syncDefaultMessage/test.tsx deleted file mode 100644 index 38e3acf7c..000000000 --- a/scripts/i18n/syncDefaultMessage/test.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export function TestComponent() { - return
Test
; -} diff --git a/scripts/i18n/syncDefaultMessage/test2.tsx b/scripts/i18n/syncDefaultMessage/test2.tsx deleted file mode 100644 index 1d918f4df..000000000 --- a/scripts/i18n/syncDefaultMessage/test2.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export function TestComponent() { - const intl = useIntl(); - return ( -
{intl.formatMessage({ id: "myKey", defaultMessage: "Test" })}
- ); -} diff --git a/turbo.json b/turbo.json index 06f204cb4..7feb6bb0d 100644 --- a/turbo.json +++ b/turbo.json @@ -12,6 +12,7 @@ }, "lint": { "dependsOn": [] }, "test": {}, - "check-types": {} + "check-types": {}, + "format": { "dependsOn": [] } } } diff --git a/yarn.lock b/yarn.lock index ab552d75f..84a8054a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5987,7 +5987,6 @@ __metadata: lint-staged: "npm:^15.5.2" motion: "npm:^12.10.0" playwright: "npm:^1.54.2" - prettier: "npm:^3.5.3" react: "npm:^19.1.0" react-dom: "npm:^19.1.0" rollup: "npm:^4.40.2" @@ -6084,7 +6083,6 @@ __metadata: ioredis: "npm:^5.6.1" pino: "npm:^9.6.0" pino-pretty: "npm:^13.0.0" - prettier: "npm:^3.5.3" typescript: "npm:^5.7.2" languageName: unknown linkType: soft @@ -6192,7 +6190,6 @@ __metadata: netlify-plugin-cypress: "npm:^2.2.1" next: "npm:15.3.4" next-auth: "npm:5.0.0-beta.29" - prettier: "npm:^3.5.3" react: "npm:19.1.0" react-aria-components: "npm:^1.8.0" react-day-picker: "npm:^9.6.7" @@ -16714,12 +16711,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.5.3": - version: 3.5.3 - resolution: "prettier@npm:3.5.3" +"prettier@npm:^3.6.2": + version: 3.6.2 + resolution: "prettier@npm:3.6.2" bin: prettier: bin/prettier.cjs - checksum: 10c0/3880cb90b9dc0635819ab52ff571518c35bd7f15a6e80a2054c05dbc8a3aa6e74f135519e91197de63705bcb38388ded7e7230e2178432a1468005406238b877 + checksum: 10c0/488cb2f2b99ec13da1e50074912870217c11edaddedeadc649b1244c749d15ba94e846423d062e2c4c9ae683e2d65f754de28889ba06e697ac4f988d44f45812 languageName: node linkType: hard @@ -18012,6 +18009,7 @@ __metadata: husky: "npm:^9.1.7" jiti: "npm:^1.21.0" lint-staged: "npm:^15.2.2" + prettier: "npm:^3.6.2" ts-node: "npm:^10.9.2" turbo: "npm:^2.5.2" languageName: unknown