Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * WIP first step * update internal imports in trpc * Fix most errors in scandic-web Just 100 left... * Move Props type out of trpc * Fix CategorizedFilters types * Move more schemas in hotel router * Fix deps * fix getNonContentstackUrls * Fix import error * Fix entry error handling * Fix generateMetadata metrics * Fix alertType enum * Fix duplicated types * lint:fix * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package * Fix broken imports * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package Approved-by: Linus Flood
This commit is contained in:
13
packages/common/constants/currency.ts
Normal file
13
packages/common/constants/currency.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// TODO move to better location?
|
||||
|
||||
export enum CurrencyEnum {
|
||||
DKK = "DKK",
|
||||
EUR = "EUR",
|
||||
NOK = "NOK",
|
||||
PLN = "PLN",
|
||||
SEK = "SEK",
|
||||
POINTS = "Points",
|
||||
Voucher = "Voucher",
|
||||
CC = "CC",
|
||||
Unknown = "Unknown",
|
||||
}
|
||||
11
packages/common/constants/membershipLevels.ts
Normal file
11
packages/common/constants/membershipLevels.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export enum MembershipLevelEnum {
|
||||
L1 = "L1",
|
||||
L2 = "L2",
|
||||
L3 = "L3",
|
||||
L4 = "L4",
|
||||
L5 = "L5",
|
||||
L6 = "L6",
|
||||
L7 = "L7",
|
||||
}
|
||||
|
||||
export type MembershipLevel = keyof typeof MembershipLevelEnum
|
||||
23
packages/common/constants/paymentMethod.ts
Normal file
23
packages/common/constants/paymentMethod.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// TODO move to better location?
|
||||
|
||||
export enum PaymentMethodEnum {
|
||||
card = "card",
|
||||
swish = "swish",
|
||||
vipps = "vipps",
|
||||
mobilePay = "mobilePay",
|
||||
applePay = "applePay",
|
||||
googlePay = "googlePay",
|
||||
alipayPlus = "alipayPlus",
|
||||
weChatPay = "weChatPay",
|
||||
payPal = "payPal",
|
||||
klarna = "klarna",
|
||||
americanExpress = "americanExpress",
|
||||
dankort = "dankort",
|
||||
dinersClub = "dinersClub",
|
||||
jcb = "jcb",
|
||||
masterCard = "masterCard",
|
||||
visa = "visa",
|
||||
maestro = "maestro",
|
||||
chinaUnionPay = "chinaUnionPay",
|
||||
discover = "discover",
|
||||
}
|
||||
19
packages/common/constants/routes/findMyBooking.ts
Normal file
19
packages/common/constants/routes/findMyBooking.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { LangRoute } from "./langRoute"
|
||||
|
||||
export const findMyBooking: LangRoute = {
|
||||
da: "/da/hotelreservation/hent-booking",
|
||||
de: "/de/hotelreservation/mein-bereich",
|
||||
en: "/en/hotelreservation/get-booking",
|
||||
fi: "/fi/hotelreservation/hae-varaus",
|
||||
no: "/no/hotelreservation/get-booking",
|
||||
sv: "/sv/hotelreservation/hitta-bokning",
|
||||
}
|
||||
|
||||
export const findMyBookingCurrentWebPath: LangRoute = {
|
||||
da: "/hotelreservation/hent-booking",
|
||||
de: "/hotelreservation/mein-bereich",
|
||||
en: "/hotelreservation/get-booking",
|
||||
fi: "/varaa-hotelli/hae-varaus",
|
||||
no: "/hotelreservation/get-booking",
|
||||
sv: "/hotelreservation/hitta-bokning",
|
||||
}
|
||||
3
packages/common/constants/routes/langRoute.ts
Normal file
3
packages/common/constants/routes/langRoute.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||
|
||||
export type LangRoute = Record<Lang, string>
|
||||
19
packages/common/constants/routes/myStay.ts
Normal file
19
packages/common/constants/routes/myStay.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { LangRoute } from "@scandic-hotels/common/constants/routes/langRoute"
|
||||
|
||||
export const myStay: LangRoute = {
|
||||
da: "/da/hotelreservation/min-ophold",
|
||||
de: "/de/hotelreservation/meine-aufenthalte",
|
||||
en: "/en/hotelreservation/my-stay",
|
||||
fi: "/fi/hotelreservation/min-vistelma",
|
||||
no: "/no/hotelreservation/min-ophold",
|
||||
sv: "/sv/hotelreservation/min-vistelse",
|
||||
}
|
||||
|
||||
export const preliminaryReceipt: LangRoute = {
|
||||
da: `${myStay.da}/receipt`,
|
||||
de: `${myStay.de}/receipt`,
|
||||
en: `${myStay.en}/receipt`,
|
||||
fi: `${myStay.fi}/receipt`,
|
||||
no: `${myStay.no}/receipt`,
|
||||
sv: `${myStay.sv}/receipt`,
|
||||
}
|
||||
41
packages/common/dt/dt.ts
Normal file
41
packages/common/dt/dt.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import "dayjs/locale/da"
|
||||
import "dayjs/locale/de"
|
||||
import "dayjs/locale/fi"
|
||||
import "dayjs/locale/sv"
|
||||
|
||||
import d from "dayjs"
|
||||
import nb from "dayjs/locale/nb"
|
||||
import advancedFormat from "dayjs/plugin/advancedFormat"
|
||||
import customParseFormat from "dayjs/plugin/customParseFormat"
|
||||
import duration from "dayjs/plugin/duration"
|
||||
import isBetween from "dayjs/plugin/isBetween"
|
||||
import isSameOrAfter from "dayjs/plugin/isSameOrAfter"
|
||||
import isSameOrBefore from "dayjs/plugin/isSameOrBefore"
|
||||
import isToday from "dayjs/plugin/isToday"
|
||||
import relativeTime from "dayjs/plugin/relativeTime"
|
||||
import timezone from "dayjs/plugin/timezone"
|
||||
import utc from "dayjs/plugin/utc"
|
||||
|
||||
/**
|
||||
* dayjs export Norwegian as nb [Norwegian Bokmål] so here we create the same
|
||||
* setup as nb has.
|
||||
* https://day.js.org/docs/en/customization/customization
|
||||
* https://github.com/iamkun/dayjs/blob/dev/src/locale/nb.js
|
||||
*/
|
||||
d.locale("no", { ...nb, name: "no" }, true)
|
||||
|
||||
/**
|
||||
* If more plugins are needed https://day.js.org/docs/en/plugin/plugin
|
||||
*/
|
||||
d.extend(advancedFormat)
|
||||
d.extend(isToday)
|
||||
d.extend(relativeTime)
|
||||
d.extend(timezone)
|
||||
d.extend(utc)
|
||||
d.extend(isSameOrAfter)
|
||||
d.extend(isSameOrBefore)
|
||||
d.extend(duration)
|
||||
d.extend(customParseFormat)
|
||||
d.extend(isBetween)
|
||||
|
||||
export const dt = d
|
||||
@@ -15,9 +15,20 @@
|
||||
"./dataCache": "./dataCache/index.ts",
|
||||
"./telemetry": "./telemetry/index.ts",
|
||||
"./tokenManager": "./tokenManager/index.ts",
|
||||
"./dt": "./dt/dt.ts",
|
||||
"./utils/isEdge": "./utils/isEdge.ts",
|
||||
"./utils/safeTry": "./utils/safeTry.ts",
|
||||
"./constants/language": "./constants/language.ts"
|
||||
"./utils/url": "./utils/url.ts",
|
||||
"./utils/languages": "./utils/languages.ts",
|
||||
"./utils/chunk": "./utils/chunk.ts",
|
||||
"./utils/zod/stringValidator": "./utils/zod/stringValidator.ts",
|
||||
"./utils/zod/numberValidator": "./utils/zod/numberValidator.ts",
|
||||
"./utils/zod/arrayValidator": "./utils/zod/arrayValidator.ts",
|
||||
"./constants/language": "./constants/language.ts",
|
||||
"./constants/membershipLevels": "./constants/membershipLevels.ts",
|
||||
"./constants/paymentMethod": "./constants/paymentMethod.ts",
|
||||
"./constants/currency": "./constants/currency.ts",
|
||||
"./constants/routes/*": "./constants/routes/*.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
|
||||
25
packages/common/utils/chunk.test.ts
Normal file
25
packages/common/utils/chunk.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { describe, expect } from "vitest"
|
||||
|
||||
import { chunk } from "./chunk"
|
||||
|
||||
describe("chunk", () => {
|
||||
it("should split an array into equally sized chunks of specified size", () => {
|
||||
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
const size = 3
|
||||
const expected = [
|
||||
[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9],
|
||||
]
|
||||
|
||||
expect(chunk(array, size)).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should split an array into equally sized chunks of specified size", () => {
|
||||
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
const size = 4
|
||||
const expected = [[1, 2, 3, 4], [5, 6, 7, 8], [9]]
|
||||
|
||||
expect(chunk(array, size)).toEqual(expected)
|
||||
})
|
||||
})
|
||||
11
packages/common/utils/chunk.ts
Normal file
11
packages/common/utils/chunk.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Splits an array into chunks of a specified size
|
||||
*/
|
||||
export function chunk<T>(array: T[], size: number): T[][] {
|
||||
const result: T[][] = []
|
||||
for (let i = 0; i < array.length; i += size) {
|
||||
result.push(array.slice(i, i + size))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
29
packages/common/utils/languages.ts
Normal file
29
packages/common/utils/languages.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { Lang } from "../constants/language"
|
||||
|
||||
export const languageSchema = z.preprocess(
|
||||
(arg) => (typeof arg === "string" ? arg.toLowerCase() : arg),
|
||||
z.nativeEnum(Lang)
|
||||
)
|
||||
|
||||
export function isValidLang(lang?: string): lang is Lang {
|
||||
const result = languageSchema.safeParse(lang)
|
||||
return result.success
|
||||
}
|
||||
|
||||
export function findLang(pathname: string): Lang | undefined {
|
||||
const langFromPath = Object.values(Lang).find(
|
||||
(l) => pathname.startsWith(`/${l}/`) || pathname === `/${l}`
|
||||
)
|
||||
|
||||
return isValidLang(langFromPath) ? langFromPath : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert lang string to Lang enum.
|
||||
*/
|
||||
export function toLang(lang: string): Lang | undefined {
|
||||
const lowerCaseLang = lang.toLowerCase()
|
||||
return Object.values(Lang).find((l) => l === lowerCaseLang)
|
||||
}
|
||||
11
packages/common/utils/url.ts
Normal file
11
packages/common/utils/url.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export function removeMultipleSlashes(pathname: string) {
|
||||
return pathname.replaceAll(/\/\/+/g, "/")
|
||||
}
|
||||
|
||||
export function removeTrailingSlash(pathname: string) {
|
||||
if (pathname.endsWith("/")) {
|
||||
// Remove the trailing slash
|
||||
return pathname.slice(0, -1)
|
||||
}
|
||||
return pathname
|
||||
}
|
||||
17
packages/common/utils/zod/arrayValidator.ts
Normal file
17
packages/common/utils/zod/arrayValidator.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { nullableStringValidator } from "./stringValidator"
|
||||
|
||||
import type { ZodObject, ZodRawShape } from "zod"
|
||||
|
||||
export function nullableArrayObjectValidator<T extends ZodRawShape>(
|
||||
schema: ZodObject<T>
|
||||
) {
|
||||
return schema
|
||||
.array()
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : []))
|
||||
}
|
||||
|
||||
export const nullableArrayStringValidator = nullableStringValidator
|
||||
.array()
|
||||
.nullish()
|
||||
.transform((arr) => (arr ? arr.filter(Boolean) : []))
|
||||
12
packages/common/utils/zod/numberValidator.ts
Normal file
12
packages/common/utils/zod/numberValidator.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const nullableNumberValidator = z
|
||||
.number()
|
||||
.nullish()
|
||||
.transform((num) => (typeof num === "number" ? num : 0))
|
||||
|
||||
export const nullableIntValidator = z
|
||||
.number()
|
||||
.int()
|
||||
.nullish()
|
||||
.transform((num) => (typeof num === "number" ? num : 0))
|
||||
18
packages/common/utils/zod/stringValidator.ts
Normal file
18
packages/common/utils/zod/stringValidator.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const nullableStringValidator = z
|
||||
.string()
|
||||
.nullish()
|
||||
.transform((str) => (str ? str : ""))
|
||||
|
||||
export const nullableStringEmailValidator = z
|
||||
.string()
|
||||
.email()
|
||||
.nullish()
|
||||
.transform((str) => (str ? str : ""))
|
||||
|
||||
export const nullableStringUrlValidator = z
|
||||
.string()
|
||||
.url()
|
||||
.nullish()
|
||||
.transform((str) => (str ? str : ""))
|
||||
Reference in New Issue
Block a user