Merge branch 'main' into testE2E-timezone
This commit is contained in:
commit
3c64bc3500
|
@ -115,6 +115,10 @@ SENDGRID_API_KEY=
|
|||
SENDGRID_EMAIL=
|
||||
NEXT_PUBLIC_SENDGRID_SENDER_NAME=
|
||||
|
||||
# Sentry
|
||||
# Used for capturing exceptions and logging messages
|
||||
NEXT_PUBLIC_SENTRY_DSN=
|
||||
|
||||
# Twilio
|
||||
# Used to send SMS reminders in workflows
|
||||
TWILIO_SID=
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
name: "Welcome new contributors"
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: opened
|
||||
pull_request:
|
||||
types: opened
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
welcome-message:
|
||||
name: Welcoming New Users
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- uses: actions/first-interaction@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr-message: |-
|
||||
Thank you for making your first Pull Request and taking the time to improve Cal.com ! ❤️🎉
|
||||
Feel free to join our [discord](https://go.cal.com/discord) and post your PR link to [collect XP and win prizes!](https://cal.com/blog/community-incentives)
|
||||
issue-message: |
|
||||
Thank you for opening your first issue, one of our team members will review it as soon as it possible. ❤️🎉
|
|
@ -30,7 +30,7 @@
|
|||
"@calcom/lib": "*",
|
||||
"@calcom/prisma": "*",
|
||||
"@calcom/trpc": "*",
|
||||
"@sentry/nextjs": "^7.20.0",
|
||||
"@sentry/nextjs": "^7.73.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"memory-cache": "^0.2.0",
|
||||
"next": "^13.4.6",
|
||||
|
|
|
@ -3,6 +3,7 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
|
|||
const os = require("os");
|
||||
const englishTranslation = require("./public/static/locales/en/common.json");
|
||||
const { withAxiom } = require("next-axiom");
|
||||
const { withSentryConfig } = require("@sentry/nextjs");
|
||||
const { version } = require("./package.json");
|
||||
const { i18n } = require("./next-i18next.config");
|
||||
const {
|
||||
|
@ -92,6 +93,7 @@ if (process.env.ANALYZE === "true") {
|
|||
}
|
||||
|
||||
plugins.push(withAxiom);
|
||||
|
||||
const matcherConfigRootPath = {
|
||||
has: [
|
||||
{
|
||||
|
@ -547,4 +549,13 @@ const nextConfig = {
|
|||
},
|
||||
};
|
||||
|
||||
if (!!process.env.NEXT_PUBLIC_SENTRY_DSN) {
|
||||
nextConfig["sentry"] = {
|
||||
autoInstrumentServerFunctions: true,
|
||||
hideSourceMaps: true,
|
||||
};
|
||||
|
||||
plugins.push(withSentryConfig);
|
||||
}
|
||||
|
||||
module.exports = () => plugins.reduce((acc, next) => next(acc), nextConfig);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@calcom/web",
|
||||
"version": "3.4.6",
|
||||
"version": "3.4.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"analyze": "ANALYZE=true next build",
|
||||
|
@ -57,6 +57,7 @@
|
|||
"@radix-ui/react-switch": "^1.0.0",
|
||||
"@radix-ui/react-toggle-group": "^1.0.0",
|
||||
"@radix-ui/react-tooltip": "^1.0.0",
|
||||
"@sentry/nextjs": "^7.73.0",
|
||||
"@stripe/react-stripe-js": "^1.10.0",
|
||||
"@stripe/stripe-js": "^1.35.0",
|
||||
"@tanstack/react-query": "^4.3.9",
|
||||
|
|
|
@ -1232,7 +1232,7 @@
|
|||
"recordings_are_part_of_the_teams_plan": "Recordings are part of the teams plan",
|
||||
"team_feature_teams": "This is a Team feature. Upgrade to Team to see your team's availability.",
|
||||
"team_feature_workflows": "This is a Team feature. Upgrade to Team to automate your event notifications and reminders with Workflows.",
|
||||
"show_eventtype_on_profile": "Show on Profile",
|
||||
"show_eventtype_on_profile": "Show on profile",
|
||||
"embed": "Embed",
|
||||
"new_username": "New username",
|
||||
"current_username": "Current username",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export {};
|
|
@ -0,0 +1 @@
|
|||
export {};
|
|
@ -0,0 +1,6 @@
|
|||
import * as Sentry from "@sentry/nextjs";
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
tracesSampleRate: 0,
|
||||
});
|
|
@ -4,6 +4,7 @@ import prismock from "../../../../tests/libs/__mocks__/prisma";
|
|||
import { diff } from "jest-diff";
|
||||
import { describe, expect, vi, beforeEach, afterEach, test } from "vitest";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import type { BookingStatus } from "@calcom/prisma/enums";
|
||||
import type { Slot } from "@calcom/trpc/server/routers/viewer/slots/types";
|
||||
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
|
||||
|
@ -874,6 +875,124 @@ describe("getSchedule", () => {
|
|||
}
|
||||
);
|
||||
});
|
||||
test("test that booking limit is working correctly if user is all day available", async () => {
|
||||
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
||||
const { dateString: plus3DateString } = getDate({ dateIncrement: 3 });
|
||||
|
||||
const scenarioData = {
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
length: 60,
|
||||
beforeEventBuffer: 0,
|
||||
afterEventBuffer: 0,
|
||||
bookingLimits: {
|
||||
PER_DAY: 1,
|
||||
},
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
length: 60,
|
||||
beforeEventBuffer: 0,
|
||||
afterEventBuffer: 0,
|
||||
bookingLimits: {
|
||||
PER_DAY: 2,
|
||||
},
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
users: [
|
||||
{
|
||||
...TestData.users.example,
|
||||
id: 101,
|
||||
schedules: [
|
||||
{
|
||||
id: 1,
|
||||
name: "All Day available",
|
||||
availability: [
|
||||
{
|
||||
userId: null,
|
||||
eventTypeId: null,
|
||||
days: [0, 1, 2, 3, 4, 5, 6],
|
||||
startTime: new Date("1970-01-01T00:00:00.000Z"),
|
||||
endTime: new Date("1970-01-01T23:59:59.999Z"),
|
||||
date: null,
|
||||
},
|
||||
],
|
||||
timeZone: Timezones["+6:00"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bookings: [
|
||||
{
|
||||
userId: 101,
|
||||
eventTypeId: 1,
|
||||
startTime: `${plus2DateString}T08:00:00.000Z`,
|
||||
endTime: `${plus2DateString}T09:00:00.000Z`,
|
||||
status: "ACCEPTED" as BookingStatus,
|
||||
},
|
||||
{
|
||||
userId: 101,
|
||||
eventTypeId: 2,
|
||||
startTime: `${plus2DateString}T08:00:00.000Z`,
|
||||
endTime: `${plus2DateString}T09:00:00.000Z`,
|
||||
status: "ACCEPTED" as BookingStatus,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const thisUserAvailabilityBookingLimitOne = await getSchedule({
|
||||
input: {
|
||||
eventTypeId: 1,
|
||||
eventTypeSlug: "",
|
||||
startTime: `${plus1DateString}T00:00:00.000Z`,
|
||||
endTime: `${plus3DateString}T23:59:59.999Z`,
|
||||
timeZone: Timezones["+6:00"],
|
||||
isTeamEvent: false,
|
||||
},
|
||||
});
|
||||
|
||||
const thisUserAvailabilityBookingLimitTwo = await getSchedule({
|
||||
input: {
|
||||
eventTypeId: 2,
|
||||
eventTypeSlug: "",
|
||||
startTime: `${plus1DateString}T00:00:00.000Z`,
|
||||
endTime: `${plus3DateString}T23:59:59.999Z`,
|
||||
timeZone: Timezones["+6:00"],
|
||||
isTeamEvent: false,
|
||||
},
|
||||
});
|
||||
|
||||
let availableSlotsInTz: dayjs.Dayjs[] = [];
|
||||
for (const date in thisUserAvailabilityBookingLimitOne.slots) {
|
||||
thisUserAvailabilityBookingLimitOne.slots[date].forEach((timeObj) => {
|
||||
availableSlotsInTz.push(dayjs(timeObj.time).tz(Timezones["+6:00"]));
|
||||
});
|
||||
}
|
||||
|
||||
expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0); // 1 booking per day as limit
|
||||
|
||||
availableSlotsInTz = [];
|
||||
for (const date in thisUserAvailabilityBookingLimitTwo.slots) {
|
||||
thisUserAvailabilityBookingLimitTwo.slots[date].forEach((timeObj) => {
|
||||
availableSlotsInTz.push(dayjs(timeObj.time).tz(Timezones["+6:00"]));
|
||||
});
|
||||
}
|
||||
expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(23); // 2 booking per day as limit, only one booking on that
|
||||
});
|
||||
});
|
||||
|
||||
describe("Team Event", () => {
|
||||
|
|
|
@ -101,6 +101,9 @@ export type InputEventType = {
|
|||
requiresConfirmation?: boolean;
|
||||
destinationCalendar?: Prisma.DestinationCalendarCreateInput;
|
||||
schedule?: InputUser["schedules"][number];
|
||||
bookingLimits?: {
|
||||
PER_DAY?: number;
|
||||
};
|
||||
} & Partial<Omit<Prisma.EventTypeCreateInput, "users" | "schedule">>;
|
||||
|
||||
type WhiteListedBookingProps = {
|
||||
|
@ -199,6 +202,7 @@ async function addEventTypes(eventTypes: InputEventType[], usersStore: InputUser
|
|||
timeZone: null,
|
||||
beforeEventBuffer: 0,
|
||||
afterEventBuffer: 0,
|
||||
bookingLimits: {},
|
||||
schedulingType: null,
|
||||
length: 15,
|
||||
//TODO: What is the purpose of periodStartDate and periodEndDate? Test these?
|
||||
|
|
|
@ -408,22 +408,7 @@ async function ensureAvailableUsers(
|
|||
|
||||
let foundConflict = false;
|
||||
try {
|
||||
if (
|
||||
eventType.recurringEvent &&
|
||||
recurringDatesInfo?.currentRecurringIndex === 0 &&
|
||||
recurringDatesInfo.allRecurringDates
|
||||
) {
|
||||
const allBookingDates = recurringDatesInfo.allRecurringDates.map((strDate) => new Date(strDate));
|
||||
// Go through each date for the recurring event and check if each one's availability
|
||||
// DONE: Decreased computational complexity from O(2^n) to O(n) by refactoring this loop to stop
|
||||
// running at the first unavailable time.
|
||||
let i = 0;
|
||||
while (!foundConflict && i < allBookingDates.length) {
|
||||
foundConflict = checkForConflicts(bufferedBusyTimes, allBookingDates[i++], duration);
|
||||
}
|
||||
} else {
|
||||
foundConflict = checkForConflicts(bufferedBusyTimes, input.dateFrom, duration);
|
||||
}
|
||||
} catch {
|
||||
log.debug({
|
||||
message: "Unable set isAvailableToBeBooked. Using true. ",
|
||||
|
@ -882,7 +867,12 @@ async function handler(
|
|||
) {
|
||||
const startAsDate = dayjs(reqBody.start).toDate();
|
||||
if (eventType.bookingLimits) {
|
||||
await checkBookingLimits(eventType.bookingLimits as IntervalLimit, startAsDate, eventType.id);
|
||||
await checkBookingLimits(
|
||||
eventType.bookingLimits as IntervalLimit,
|
||||
startAsDate,
|
||||
eventType.id,
|
||||
eventType.schedule?.timeZone
|
||||
);
|
||||
}
|
||||
if (eventType.durationLimits) {
|
||||
await checkDurationLimits(eventType.durationLimits as IntervalLimit, startAsDate, eventType.id);
|
||||
|
@ -930,8 +920,8 @@ async function handler(
|
|||
}),
|
||||
},
|
||||
{
|
||||
dateFrom: reqBody.start,
|
||||
dateTo: reqBody.end,
|
||||
dateFrom: dayjs(reqBody.start).tz(reqBody.timeZone).format(),
|
||||
dateTo: dayjs(reqBody.end).tz(reqBody.timeZone).format(),
|
||||
timeZone: reqBody.timeZone,
|
||||
originalRescheduledBooking,
|
||||
},
|
||||
|
@ -998,7 +988,6 @@ async function handler(
|
|||
const attendeeTimezone = attendeeInfoOnReschedule ? attendeeInfoOnReschedule.timeZone : reqBody.timeZone;
|
||||
|
||||
const tAttendees = await getTranslation(attendeeLanguage ?? "en", "common");
|
||||
|
||||
// use host default
|
||||
if (isTeamEventType && locationBodyString === OrganizerDefaultConferencingAppType) {
|
||||
const metadataParseResult = userMetadataSchema.safeParse(organizerUser.metadata);
|
||||
|
|
|
@ -64,16 +64,19 @@ const getReturnUrl = (props: Props) => {
|
|||
};
|
||||
|
||||
const PaymentForm = (props: Props) => {
|
||||
const {
|
||||
user: { username },
|
||||
} = props;
|
||||
const { t, i18n } = useLocale();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [state, setState] = useState<States>({ status: "idle" });
|
||||
const [isCanceling, setIsCanceling] = useState<boolean>(false);
|
||||
const stripe = useStripe();
|
||||
const elements = useElements();
|
||||
const paymentOption = props.payment.paymentOption;
|
||||
const [holdAcknowledged, setHoldAcknowledged] = useState<boolean>(paymentOption === "HOLD" ? false : true);
|
||||
const bookingSuccessRedirect = useBookingSuccessRedirect();
|
||||
|
||||
useEffect(() => {
|
||||
elements?.update({ locale: i18n.language as StripeElementLocale });
|
||||
}, [elements, i18n.language]);
|
||||
|
@ -134,6 +137,8 @@ const PaymentForm = (props: Props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const disableButtons = isCanceling || !holdAcknowledged || ["processing", "error"].includes(state.status);
|
||||
|
||||
return (
|
||||
<form id="payment-form" className="bg-subtle mt-4 rounded-md p-6" onSubmit={handleSubmit}>
|
||||
<div>
|
||||
|
@ -154,14 +159,22 @@ const PaymentForm = (props: Props) => {
|
|||
<div className="mt-2 flex justify-end space-x-2">
|
||||
<Button
|
||||
color="minimal"
|
||||
disabled={!holdAcknowledged || ["processing", "error"].includes(state.status)}
|
||||
disabled={disableButtons}
|
||||
id="cancel"
|
||||
onClick={() => router.back()}>
|
||||
type="button"
|
||||
loading={isCanceling}
|
||||
onClick={() => {
|
||||
setIsCanceling(true);
|
||||
if (username) {
|
||||
return router.push(`/${username}`);
|
||||
}
|
||||
return router.back();
|
||||
}}>
|
||||
<span id="button-text">{t("cancel")}</span>
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!holdAcknowledged || ["processing", "error"].includes(state.status)}
|
||||
disabled={disableButtons}
|
||||
loading={state.status === "processing"}
|
||||
id="submit"
|
||||
color="secondary">
|
||||
|
|
|
@ -179,6 +179,38 @@ describe("processWorkingHours", () => {
|
|||
expect(allDSTStartAt12).toBeTruthy();
|
||||
expect(allNotDSTStartAt13).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should skip event if it ends before it starts (different days)", () => {
|
||||
const item = {
|
||||
days: [1, 2, 3],
|
||||
startTime: new Date(new Date().setUTCHours(8, 0, 0, 0)), // 8 AM
|
||||
endTime: new Date(new Date().setUTCHours(7, 0, 0, 0)), // 7 AM
|
||||
};
|
||||
|
||||
const timeZone = "America/New_York";
|
||||
const dateFrom = dayjs("2023-11-07T00:00:00Z").tz(timeZone); // 2023-11-07T00:00:00 (America/New_York)
|
||||
const dateTo = dayjs("2023-11-08T00:00:00Z").tz(timeZone); // 2023-11-08T00:00:00 (America/New_York)
|
||||
|
||||
const results = processWorkingHours({ item, timeZone, dateFrom, dateTo });
|
||||
|
||||
expect(results).toEqual([]);
|
||||
});
|
||||
|
||||
it("should skip event if it ends before it starts (same day but different hours)", () => {
|
||||
const item = {
|
||||
days: [1],
|
||||
startTime: new Date(new Date().setUTCHours(8, 0, 0, 0)), // 8 AM
|
||||
endTime: new Date(new Date().setUTCHours(7, 0, 0, 0)), // 7 AM
|
||||
};
|
||||
|
||||
const timeZone = "America/New_York";
|
||||
const dateFrom = dayjs("2023-11-07T00:00:00Z").tz(timeZone); // 2023-11-07T00:00:00 (America/New_York)
|
||||
const dateTo = dayjs("2023-11-07T23:59:59Z").tz(timeZone); // 2023-11-07T23:59:59 (America/New_York)
|
||||
|
||||
const results = processWorkingHours({ item, timeZone, dateFrom, dateTo });
|
||||
|
||||
expect(results).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("processDateOverrides", () => {
|
||||
|
|
|
@ -47,7 +47,11 @@ export function processWorkingHours({
|
|||
const startResult = dayjs.max(start, dateFrom.tz(timeZone));
|
||||
const endResult = dayjs.min(end, dateTo.tz(timeZone));
|
||||
|
||||
if (startResult.isAfter(endResult)) {
|
||||
const isLater =
|
||||
startResult.isAfter(endResult, "hour") ||
|
||||
(startResult.isSame(endResult, "hour") && startResult.isAfter(endResult, "minute"));
|
||||
|
||||
if (isLater) {
|
||||
// if an event ends before start, it's not a result.
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { renderHook } from "@testing-library/react-hooks";
|
||||
import { vi } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { useParamsWithFallback } from "./useParamsWithFallback";
|
||||
|
||||
describe("useParamsWithFallback hook", () => {
|
||||
it("should return router.query when param is null", () => {
|
||||
vi.mock("next/navigation", () => ({
|
||||
useParams: vi.fn().mockReturnValue(null),
|
||||
}));
|
||||
|
||||
vi.mock("next/compat/router", () => ({
|
||||
useRouter: vi.fn().mockReturnValue({ query: { id: 1 } }),
|
||||
}));
|
||||
|
||||
const { result } = renderHook(() => useParamsWithFallback());
|
||||
|
||||
expect(result.current).toEqual({ id: 1 });
|
||||
});
|
||||
|
||||
it("should return router.query when param is undefined", () => {
|
||||
vi.mock("next/navigation", () => ({
|
||||
useParams: vi.fn().mockReturnValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("next/compat/router", () => ({
|
||||
useRouter: vi.fn().mockReturnValue({ query: { id: 1 } }),
|
||||
}));
|
||||
|
||||
const { result } = renderHook(() => useParamsWithFallback());
|
||||
|
||||
expect(result.current).toEqual({ id: 1 });
|
||||
});
|
||||
|
||||
it("should return useParams() if it exists", () => {
|
||||
vi.mock("next/navigation", () => ({
|
||||
useParams: vi.fn().mockReturnValue({ id: 1 }),
|
||||
}));
|
||||
|
||||
vi.mock("next/compat/router", () => ({
|
||||
useRouter: vi.fn().mockReturnValue(null),
|
||||
}));
|
||||
|
||||
const { result } = renderHook(() => useParamsWithFallback());
|
||||
|
||||
expect(result.current).toEqual({ id: 1 });
|
||||
});
|
||||
|
||||
it("should return useParams() if it exists", () => {
|
||||
vi.mock("next/navigation", () => ({
|
||||
useParams: vi.fn().mockReturnValue({ id: 1 }),
|
||||
}));
|
||||
|
||||
vi.mock("next/compat/router", () => ({
|
||||
useRouter: vi.fn().mockReturnValue({ query: { id: 2 } }),
|
||||
}));
|
||||
|
||||
const { result } = renderHook(() => useParamsWithFallback());
|
||||
|
||||
expect(result.current).toEqual({ id: 1 });
|
||||
});
|
||||
});
|
|
@ -1,13 +1,18 @@
|
|||
"use client";
|
||||
|
||||
import { useRouter as useCompatRouter } from "next/compat/router";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useRouter } from "next/router";
|
||||
import type { ParsedUrlQuery } from "querystring";
|
||||
|
||||
interface Params {
|
||||
[key: string]: string | string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook is a workaround until pages are migrated to app directory.
|
||||
*/
|
||||
export function useParamsWithFallback() {
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
return params || router.query;
|
||||
export function useParamsWithFallback(): Params | ParsedUrlQuery {
|
||||
const params = useParams(); // always `null` in pages router
|
||||
const router = useCompatRouter(); // always `null` in app router
|
||||
return params ?? router?.query ?? {};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,12 @@ import { parseZone } from "./parse-zone";
|
|||
|
||||
type ExtraOptions = { withDefaultTimeFormat?: boolean; selectedTimeFormat?: TimeFormat };
|
||||
|
||||
const processDate = (date: string | null | Dayjs, language: string, options?: ExtraOptions) => {
|
||||
const processDate = (
|
||||
date: string | null | Dayjs,
|
||||
language: string,
|
||||
timeZone: string,
|
||||
options?: ExtraOptions
|
||||
) => {
|
||||
const parsedZone = parseZone(date);
|
||||
if (!parsedZone?.isValid()) return "Invalid date";
|
||||
const formattedTime = parsedZone?.format(
|
||||
|
@ -17,12 +22,19 @@ const processDate = (date: string | null | Dayjs, language: string, options?: Ex
|
|||
? TimeFormat.TWELVE_HOUR
|
||||
: options?.selectedTimeFormat || detectBrowserTimeFormat
|
||||
);
|
||||
return `${formattedTime}, ${dayjs(date).toDate().toLocaleString(language, { dateStyle: "full" })}`;
|
||||
return `${formattedTime}, ${dayjs(date)
|
||||
.toDate()
|
||||
.toLocaleString(language, { dateStyle: "full", timeZone })}`;
|
||||
};
|
||||
|
||||
export const parseDate = (date: string | null | Dayjs, language: string, options?: ExtraOptions) => {
|
||||
export const parseDate = (
|
||||
date: string | null | Dayjs,
|
||||
language: string,
|
||||
timeZone: string,
|
||||
options?: ExtraOptions
|
||||
) => {
|
||||
if (!date) return ["No date"];
|
||||
return processDate(date, language, options);
|
||||
return processDate(date, language, timeZone, options);
|
||||
};
|
||||
|
||||
const timeOptions: Intl.DateTimeFormatOptions = {
|
||||
|
@ -74,7 +86,7 @@ export const parseRecurringDates = (
|
|||
withDefaultTimeFormat,
|
||||
}: {
|
||||
startDate: string | null | Dayjs;
|
||||
timeZone?: string;
|
||||
timeZone: string;
|
||||
recurringEvent: RecurringEvent | null;
|
||||
recurringCount: number;
|
||||
selectedTimeFormat?: TimeFormat;
|
||||
|
@ -98,7 +110,7 @@ export const parseRecurringDates = (
|
|||
});
|
||||
const dateStrings = times.map((t) => {
|
||||
// finally; show in local timeZone again
|
||||
return processDate(t.tz(timeZone), language, { selectedTimeFormat, withDefaultTimeFormat });
|
||||
return processDate(t.tz(timeZone), language, timeZone, { selectedTimeFormat, withDefaultTimeFormat });
|
||||
});
|
||||
|
||||
return [dateStrings, times.map((t) => t.toDate())];
|
||||
|
|
|
@ -11,14 +11,15 @@ import { parseBookingLimit } from "../isBookingLimits";
|
|||
export async function checkBookingLimits(
|
||||
bookingLimits: IntervalLimit,
|
||||
eventStartDate: Date,
|
||||
eventId: number
|
||||
eventId: number,
|
||||
timeZone?: string | null
|
||||
) {
|
||||
const parsedBookingLimits = parseBookingLimit(bookingLimits);
|
||||
if (!parsedBookingLimits) return false;
|
||||
|
||||
// not iterating entries to preserve types
|
||||
const limitCalculations = ascendingLimitKeys.map((key) =>
|
||||
checkBookingLimit({ key, limitingNumber: parsedBookingLimits[key], eventStartDate, eventId })
|
||||
checkBookingLimit({ key, limitingNumber: parsedBookingLimits[key], eventStartDate, eventId, timeZone })
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -33,19 +34,23 @@ export async function checkBookingLimit({
|
|||
eventId,
|
||||
key,
|
||||
limitingNumber,
|
||||
timeZone,
|
||||
}: {
|
||||
eventStartDate: Date;
|
||||
eventId: number;
|
||||
key: keyof IntervalLimit;
|
||||
limitingNumber: number | undefined;
|
||||
timeZone?: string | null;
|
||||
}) {
|
||||
{
|
||||
const eventDateInOrganizerTz = timeZone ? dayjs(eventStartDate).tz(timeZone) : dayjs(eventStartDate);
|
||||
|
||||
if (!limitingNumber) return;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
|
||||
const startDate = dayjs(eventStartDate).startOf(unit).toDate();
|
||||
const endDate = dayjs(eventStartDate).endOf(unit).toDate();
|
||||
const startDate = dayjs(eventDateInOrganizerTz).startOf(unit).toDate();
|
||||
const endDate = dayjs(eventDateInOrganizerTz).endOf(unit).toDate();
|
||||
|
||||
const bookingsInPeriod = await prisma.booking.count({
|
||||
where: {
|
||||
|
|
|
@ -205,7 +205,11 @@ export const stringOrNumber = z.union([
|
|||
z.number().int(),
|
||||
]);
|
||||
|
||||
export const stringToDayjs = z.string().transform((val) => dayjs(val));
|
||||
export const stringToDayjs = z.string().transform((val) => {
|
||||
const matches = val.match(/([+-]\d{2}:\d{2})$/);
|
||||
const timezone = matches ? matches[1] : "+00:00";
|
||||
return dayjs(val).utcOffset(timezone);
|
||||
});
|
||||
|
||||
export const bookingCreateBodySchema = z.object({
|
||||
end: z.string().optional(),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import * as Sentry from "@sentry/nextjs";
|
||||
|
||||
import { redactError } from "@calcom/lib/redactError";
|
||||
|
||||
import { middleware } from "../trpc";
|
||||
|
@ -9,6 +11,7 @@ const captureErrorsMiddleware = middleware(async ({ next }) => {
|
|||
if (!cause) {
|
||||
return result;
|
||||
}
|
||||
Sentry.captureException(cause);
|
||||
throw redactError(cause);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -109,7 +109,6 @@ export const updateHandler = async ({ input, ctx }: UpdateOptions) => {
|
|||
timeZone: true,
|
||||
eventType: {
|
||||
select: {
|
||||
_count: true,
|
||||
id: true,
|
||||
eventName: true,
|
||||
},
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"outputs": [".next/**"],
|
||||
"env": [
|
||||
"NEXT_PUBLIC_IS_E2E",
|
||||
"NEXT_PUBLIC_SENTRY_DSN",
|
||||
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY",
|
||||
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRODUCT_ID",
|
||||
"NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
|
||||
|
|
|
@ -36,7 +36,7 @@ const workspaces = packagedEmbedTestsOnly
|
|||
test: {
|
||||
include: ["packages/**/*.{test,spec}.{ts,js}", "apps/**/*.{test,spec}.{ts,js}"],
|
||||
// TODO: Ignore the api until tests are fixed
|
||||
exclude: ["**/node_modules/**/*", "packages/embeds/**/*"],
|
||||
exclude: ["**/node_modules/**/*", "packages/embeds/**/*", "packages/lib/hooks/**/*"],
|
||||
setupFiles: ["setupVitest.ts"],
|
||||
},
|
||||
},
|
||||
|
@ -67,6 +67,13 @@ const workspaces = packagedEmbedTestsOnly
|
|||
setupFiles: ["packages/app-store/test-setup.ts"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: "@calcom/packages/lib/hooks",
|
||||
include: ["packages/lib/hooks/**/*.{test,spec}.{ts,js}"],
|
||||
environment: "jsdom",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default defineWorkspace(workspaces);
|
||||
|
|
229
yarn.lock
229
yarn.lock
|
@ -3431,7 +3431,7 @@ __metadata:
|
|||
"@calcom/trpc": "*"
|
||||
"@calcom/tsconfig": "*"
|
||||
"@calcom/types": "*"
|
||||
"@sentry/nextjs": ^7.20.0
|
||||
"@sentry/nextjs": ^7.73.0
|
||||
bcryptjs: ^2.4.3
|
||||
memory-cache: ^0.2.0
|
||||
next: ^13.4.6
|
||||
|
@ -4515,6 +4515,7 @@ __metadata:
|
|||
"@radix-ui/react-switch": ^1.0.0
|
||||
"@radix-ui/react-toggle-group": ^1.0.0
|
||||
"@radix-ui/react-tooltip": ^1.0.0
|
||||
"@sentry/nextjs": ^7.73.0
|
||||
"@stripe/react-stripe-js": ^1.10.0
|
||||
"@stripe/stripe-js": ^1.35.0
|
||||
"@tanstack/react-query": ^4.3.9
|
||||
|
@ -10498,29 +10499,27 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry-internal/tracing@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry-internal/tracing@npm:7.53.1"
|
||||
"@sentry-internal/tracing@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry-internal/tracing@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/core": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 99fadf422e619faeea436a96b37088ba10850f8e77fca10d7fea6de0c3f1d60b0e8ec1da3b9230f4213fa25f044c99aba585562447ddca0a443d7cbd88c3b81d
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
checksum: dc6162db6d426212440abd66f9e37a4ce1849a79dd067158091702b273f3312ea131984c7aad58708745340b2a0ddb652b898c27dbf409d8691dbd4ee8a9ebde
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/browser@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/browser@npm:7.53.1"
|
||||
"@sentry/browser@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/browser@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry-internal/tracing": 7.53.1
|
||||
"@sentry/core": 7.53.1
|
||||
"@sentry/replay": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 6250949dfbef169669d9e932515f0d965f449ef82be5fb6b813ab170944cef033c758857a3412aa1a1023d77622f88d8599df8e4b0ea126479f8713bd4aa1838
|
||||
"@sentry-internal/tracing": 7.77.0
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/replay": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
checksum: b3c4ecbf27e8d940c42bc151fc39e9e3659889c0091e69a39f3b8f0e316caa9cdd17aa2c00b151ff9976eff459f023e69cb51f8efa96a840191afd4091cc7573
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -10540,112 +10539,119 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/core@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/core@npm:7.53.1"
|
||||
"@sentry/core@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/core@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 5d42bc30a59cb4459eb99441b631e3f9daec5b2e98c24377aae0329127f8c474a9c32353a96e3f4765e3fb18370756e85f6b873cd26bd591e0040917b7fa9cf4
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
checksum: f76e83ba5da4710b87b5e03f747ac5b5f93c93814447d29e1863b6bd3734d87f3a8fb197060a9a8370430d1d47b5c8c33dc86acc7f7b212322630e280435c6d8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/integrations@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/integrations@npm:7.53.1"
|
||||
"@sentry/integrations@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/integrations@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
localforage: ^1.8.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 55fc930af665afa07f81591f8898c8c10518696d48ec6d9f0864fc05fa5ef754868644f50362bac15734dff93592397ec022d80ded8754b97d64009e63a30712
|
||||
checksum: b34f1e0a5a28154698b0eb42c9a3c968c35cbe1ba0411df7b4b83008a58cb3db2a2c07eee5e7a6e55f8b6aae9c74c8433d0e97a3e6289c979b361c09ced4475a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/nextjs@npm:^7.20.0":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/nextjs@npm:7.53.1"
|
||||
"@sentry/nextjs@npm:^7.73.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/nextjs@npm:7.77.0"
|
||||
dependencies:
|
||||
"@rollup/plugin-commonjs": 24.0.0
|
||||
"@sentry/core": 7.53.1
|
||||
"@sentry/integrations": 7.53.1
|
||||
"@sentry/node": 7.53.1
|
||||
"@sentry/react": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/integrations": 7.77.0
|
||||
"@sentry/node": 7.77.0
|
||||
"@sentry/react": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
"@sentry/vercel-edge": 7.77.0
|
||||
"@sentry/webpack-plugin": 1.20.0
|
||||
chalk: 3.0.0
|
||||
resolve: 1.22.8
|
||||
rollup: 2.78.0
|
||||
stacktrace-parser: ^0.1.10
|
||||
tslib: ^1.9.3
|
||||
peerDependencies:
|
||||
next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0
|
||||
next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 || ^14.0
|
||||
react: 16.x || 17.x || 18.x
|
||||
webpack: ">= 4.0.0"
|
||||
peerDependenciesMeta:
|
||||
webpack:
|
||||
optional: true
|
||||
checksum: 3b23a986b99b69453426f32f851eb3140d7ed29f066d2bf2d2562b72b8ca786fffa0c7903f0ab6f9a83ec1defaa2f7ec58db62515f4b95bd436ce33c862644db
|
||||
checksum: 293019ff3bc85f1f041f15f1836cb98587cbecf780c26d7758a470d382042c9aa9522408853afbe16a73945f0e4edb6d5b3d704e8b8501b9d90304a6a9492afe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/node@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/node@npm:7.53.1"
|
||||
"@sentry/node@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/node@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry-internal/tracing": 7.53.1
|
||||
"@sentry/core": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
cookie: ^0.4.1
|
||||
"@sentry-internal/tracing": 7.77.0
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
https-proxy-agent: ^5.0.0
|
||||
lru_map: ^0.3.3
|
||||
tslib: ^1.9.3
|
||||
checksum: e1b3c342c75a2a5883d6f1a52bc975bd6fb06643d2c26fd302cc0cfd23ca09509374f8c3afbe16208d007dc862e58b96946125dfebd3ba5856aa791cff04cea2
|
||||
checksum: 11034db59a547f3b35208f601fa4704dc7ef6e1f9730136562c1764de8f7b286b355b701711febb44b972ed7009b3467c21ffda15f07024f7dee36979ca9e1c1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/react@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/react@npm:7.53.1"
|
||||
"@sentry/react@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/react@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/browser": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
"@sentry/browser": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
hoist-non-react-statics: ^3.3.2
|
||||
tslib: ^1.9.3
|
||||
peerDependencies:
|
||||
react: 15.x || 16.x || 17.x || 18.x
|
||||
checksum: ee08c6a851cae421a134d62e217c192a961930254ea8775e1960420307f4ff08b659405bd883b12698a55085ad1070ac58e618f5799a7edc775368382e807e2d
|
||||
checksum: 18af780c76b6b0c52ea476963b8ef0b7a346796c5d0e04dd7c4cb73eb3e52b2fd00b8c1cd5529c29983398a57e325d0d45a689bc8b9822d7c9b10339870869f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/replay@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/replay@npm:7.53.1"
|
||||
"@sentry/replay@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/replay@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/core": 7.53.1
|
||||
"@sentry/types": 7.53.1
|
||||
"@sentry/utils": 7.53.1
|
||||
checksum: c3757077a971183f5f9f87006449a110c0f951c76a777aa45cb2f057100ec5bc8fcf50e4c58e8117ddc0f44fdaada101384a45b2b5c427048b4ce57eb780711d
|
||||
"@sentry-internal/tracing": 7.77.0
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
checksum: 95bbd554a33a17273501fffadd7a51050787ef5a0ec26de5cccba35f6bfd5d88b2c13f735beaf74274cdb5f77d3a310fa2699d9629220de4b79e4d4c27a14e20
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/types@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/types@npm:7.53.1"
|
||||
checksum: 5f76d7d66d5df5d48f66a755e18ae133ea02a9405093b652eb4921ca62c3114343561a2d8067f2be6d9df8dd32d10e30d3ce58150f795600680e6230fb136681
|
||||
"@sentry/types@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/types@npm:7.77.0"
|
||||
checksum: ff8047425d4b0caae9221a9fa52fa0122ddf23b51152b7d71914f6465cf72dc3fdf00b7db16e3e95b4a1d2d429824d91ed586b1abac6d5286bd7800504e30824
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/utils@npm:7.53.1":
|
||||
version: 7.53.1
|
||||
resolution: "@sentry/utils@npm:7.53.1"
|
||||
"@sentry/utils@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/utils@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/types": 7.53.1
|
||||
tslib: ^1.9.3
|
||||
checksum: d9556f161a0eed0e1bb279bac12b99492b6212d9b6cabebbcb2d0f196f99b96c319305ec347d8f06382e2dde5782d5ba20a00f762fbfd4e8699e9100ef921804
|
||||
"@sentry/types": 7.77.0
|
||||
checksum: 000bb1caec44812dc39a8026ecba78c14a8332f15cb78d2935c91a7ba8d61eab9553a791a4af528a113ca90b83db6e81791e3562b2559b76596accc69e4d57ad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/vercel-edge@npm:7.77.0":
|
||||
version: 7.77.0
|
||||
resolution: "@sentry/vercel-edge@npm:7.77.0"
|
||||
dependencies:
|
||||
"@sentry/core": 7.77.0
|
||||
"@sentry/types": 7.77.0
|
||||
"@sentry/utils": 7.77.0
|
||||
checksum: 3c23c46af233fe3d50f48509fd8e89c24be54d79419e0368bbcc574b6f1d886ff182300e507bbe5fb587c1219ee9663eaa1591783ca0a7bbebdd85b8b35a07ad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -18555,7 +18561,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cookie@npm:0.4.2, cookie@npm:^0.4.1, cookie@npm:^0.4.2":
|
||||
"cookie@npm:0.4.2, cookie@npm:^0.4.2":
|
||||
version: 0.4.2
|
||||
resolution: "cookie@npm:0.4.2"
|
||||
checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b
|
||||
|
@ -28217,13 +28223,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lru_map@npm:^0.3.3":
|
||||
version: 0.3.3
|
||||
resolution: "lru_map@npm:0.3.3"
|
||||
checksum: ca9dd43c65ed7a4f117c548028101c5b6855e10923ea9d1f635af53ad20c5868ff428c364d454a7b57fe391b89c704982275410c3c5099cca5aeee00d76e169a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ltgt@npm:^2.1.2":
|
||||
version: 2.2.1
|
||||
resolution: "ltgt@npm:2.2.1"
|
||||
|
@ -35232,6 +35231,19 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@npm:1.22.8, resolve@npm:^1.22.2":
|
||||
version: 1.22.8
|
||||
resolution: "resolve@npm:1.22.8"
|
||||
dependencies:
|
||||
is-core-module: ^2.13.0
|
||||
path-parse: ^1.0.7
|
||||
supports-preserve-symlinks-flag: ^1.0.0
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@npm:^1.1.7, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.1, resolve@npm:^1.3.2":
|
||||
version: 1.22.1
|
||||
resolution: "resolve@npm:1.22.1"
|
||||
|
@ -35258,19 +35270,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@npm:^1.22.2":
|
||||
version: 1.22.8
|
||||
resolution: "resolve@npm:1.22.8"
|
||||
dependencies:
|
||||
is-core-module: ^2.13.0
|
||||
path-parse: ^1.0.7
|
||||
supports-preserve-symlinks-flag: ^1.0.0
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@npm:^2.0.0-next.3":
|
||||
version: 2.0.0-next.3
|
||||
resolution: "resolve@npm:2.0.0-next.3"
|
||||
|
@ -35294,6 +35293,19 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@patch:resolve@1.22.8#~builtin<compat/resolve>, resolve@patch:resolve@^1.22.2#~builtin<compat/resolve>":
|
||||
version: 1.22.8
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin<compat/resolve>::version=1.22.8&hash=c3c19d"
|
||||
dependencies:
|
||||
is-core-module: ^2.13.0
|
||||
path-parse: ^1.0.7
|
||||
supports-preserve-symlinks-flag: ^1.0.0
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@patch:resolve@^1.1.7#~builtin<compat/resolve>, resolve@patch:resolve@^1.14.2#~builtin<compat/resolve>, resolve@patch:resolve@^1.17.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.19.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.22.1#~builtin<compat/resolve>, resolve@patch:resolve@^1.3.2#~builtin<compat/resolve>":
|
||||
version: 1.22.1
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin<compat/resolve>::version=1.22.1&hash=c3c19d"
|
||||
|
@ -35320,19 +35332,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@patch:resolve@^1.22.2#~builtin<compat/resolve>":
|
||||
version: 1.22.8
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin<compat/resolve>::version=1.22.8&hash=c3c19d"
|
||||
dependencies:
|
||||
is-core-module: ^2.13.0
|
||||
path-parse: ^1.0.7
|
||||
supports-preserve-symlinks-flag: ^1.0.0
|
||||
bin:
|
||||
resolve: bin/resolve
|
||||
checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve@patch:resolve@^2.0.0-next.3#~builtin<compat/resolve>":
|
||||
version: 2.0.0-next.3
|
||||
resolution: "resolve@patch:resolve@npm%3A2.0.0-next.3#~builtin<compat/resolve>::version=2.0.0-next.3&hash=c3c19d"
|
||||
|
|
Loading…
Reference in New Issue
Block a user