fix: create event type with output of another create event type (#21273)
* feat: accept location booking field with label customization * feat: return location label * chore: bump libraries * test * fix: tests
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.197",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.202",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
+62
-2
@@ -1428,7 +1428,6 @@ describe("Event types Endpoints", () => {
|
||||
{
|
||||
name: "location",
|
||||
type: "radioInput",
|
||||
label: "",
|
||||
sources: [{ id: "default", type: "default", label: "Default" }],
|
||||
editable: "system",
|
||||
required: false,
|
||||
@@ -1558,7 +1557,6 @@ describe("Event types Endpoints", () => {
|
||||
{
|
||||
name: "location",
|
||||
type: "radioInput",
|
||||
label: "",
|
||||
sources: [{ id: "default", type: "default", label: "Default" }],
|
||||
editable: "system",
|
||||
required: false,
|
||||
@@ -1783,6 +1781,68 @@ describe("Event types Endpoints", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("creating event type with input of another event type output", () => {
|
||||
let firstCreatedEventType: EventTypeOutput_2024_06_14;
|
||||
let secondCreatedEventType: EventTypeOutput_2024_06_14;
|
||||
|
||||
it("should create first event type", async () => {
|
||||
const body: CreateEventTypeInput_2024_06_14 = {
|
||||
title: "first created coding class",
|
||||
slug: "first-created-coding-class",
|
||||
lengthInMinutes: 60,
|
||||
locations: [
|
||||
{
|
||||
type: "address",
|
||||
address: "via volturno 10, Roma",
|
||||
public: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/api/v2/event-types")
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
|
||||
.send(body)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: ApiSuccessResponse<EventTypeOutput_2024_06_14> = response.body;
|
||||
const createdEventType = responseBody.data;
|
||||
expect(createdEventType).toHaveProperty("id");
|
||||
expect(createdEventType.title).toEqual(body.title);
|
||||
expect(createdEventType.locations).toEqual(body.locations);
|
||||
firstCreatedEventType = responseBody.data;
|
||||
});
|
||||
});
|
||||
|
||||
it("should create second event type using first as input", async () => {
|
||||
const body = {
|
||||
...firstCreatedEventType,
|
||||
title: "second created coding class",
|
||||
slug: "second-created-coding-class",
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
.post("/api/v2/event-types")
|
||||
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
|
||||
.send(body)
|
||||
.expect(201)
|
||||
.then(async (response) => {
|
||||
const responseBody: ApiSuccessResponse<EventTypeOutput_2024_06_14> = response.body;
|
||||
const createdEventType = responseBody.data;
|
||||
expect(createdEventType).toHaveProperty("id");
|
||||
expect(createdEventType.title).toEqual(body.title);
|
||||
secondCreatedEventType = responseBody.data;
|
||||
|
||||
const { id, title, slug, ...restFirst } = firstCreatedEventType;
|
||||
const { id: id2, title: title2, slug: slug2, ...restSecond } = secondCreatedEventType;
|
||||
expect(restFirst).toEqual(restSecond);
|
||||
expect(id2).not.toEqual(id);
|
||||
expect(title2).not.toEqual(title);
|
||||
expect(slug2).not.toEqual(slug);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await oauthClientRepositoryFixture.delete(oAuthClient.id);
|
||||
await teamRepositoryFixture.delete(organization.id);
|
||||
|
||||
+4
-2
@@ -224,6 +224,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
const systemCustomNameField = systemCustomFields?.find((field) => field.type === "name");
|
||||
const systemCustomEmailField = systemCustomFields?.find((field) => field.type === "email");
|
||||
const systemCustomTitleField = systemCustomFields?.find((field) => field.name === "title");
|
||||
const systemCustomLocationField = systemCustomFields?.find((field) => field.name === "location");
|
||||
const systemCustomNotesField = systemCustomFields?.find((field) => field.name === "notes");
|
||||
const systemCustomGuestsField = systemCustomFields?.find((field) => field.name === "guests");
|
||||
const systemCustomRescheduleReasonField = systemCustomFields?.find(
|
||||
@@ -233,7 +234,7 @@ export class InputEventTypesService_2024_06_14 {
|
||||
const defaultFieldsBefore: (SystemField | CustomField)[] = [
|
||||
systemCustomNameField || systemBeforeFieldName,
|
||||
systemCustomEmailField || systemBeforeFieldEmail,
|
||||
systemBeforeFieldLocation,
|
||||
systemCustomLocationField || systemBeforeFieldLocation,
|
||||
];
|
||||
|
||||
const defaultFieldsAfter = [
|
||||
@@ -274,7 +275,8 @@ export class InputEventTypesService_2024_06_14 {
|
||||
field.name !== "title" &&
|
||||
field.name !== "notes" &&
|
||||
field.name !== "guests" &&
|
||||
field.name !== "rescheduleReason"
|
||||
field.name !== "rescheduleReason" &&
|
||||
field.name !== "location"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14546,6 +14546,22 @@
|
||||
"slug"
|
||||
]
|
||||
},
|
||||
"LocationDefaultFieldInput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"example": "location",
|
||||
"description": "only allowed value for type is `location`. This booking field is displayed only when event type has 2 or more locations in order to allow person doing the booking pick the location."
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"slug"
|
||||
]
|
||||
},
|
||||
"NotesDefaultFieldInput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -14759,6 +14775,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -15350,6 +15369,9 @@
|
||||
"hidden": {
|
||||
"type": "boolean",
|
||||
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -15366,11 +15388,11 @@
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"name",
|
||||
"email",
|
||||
"title",
|
||||
"location",
|
||||
"notes",
|
||||
"guests"
|
||||
"guests",
|
||||
"rescheduleReason"
|
||||
],
|
||||
"example": "rescheduleReason",
|
||||
"description": "only allowed value for type is `rescheduleReason`",
|
||||
@@ -15416,11 +15438,11 @@
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"name",
|
||||
"email",
|
||||
"title",
|
||||
"location",
|
||||
"notes",
|
||||
"guests"
|
||||
"guests",
|
||||
"rescheduleReason"
|
||||
],
|
||||
"example": "title",
|
||||
"description": "only allowed value for type is `title`",
|
||||
@@ -15466,11 +15488,11 @@
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"name",
|
||||
"email",
|
||||
"title",
|
||||
"location",
|
||||
"notes",
|
||||
"guests"
|
||||
"guests",
|
||||
"rescheduleReason"
|
||||
],
|
||||
"example": "notes",
|
||||
"description": "only allowed value for type is `notes`",
|
||||
@@ -15516,11 +15538,11 @@
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"name",
|
||||
"email",
|
||||
"title",
|
||||
"location",
|
||||
"notes",
|
||||
"guests"
|
||||
"guests",
|
||||
"rescheduleReason"
|
||||
],
|
||||
"example": "guests",
|
||||
"description": "only allowed value for type is `guests`",
|
||||
@@ -16749,6 +16771,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -18563,6 +18588,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -19421,6 +19449,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
|
||||
@@ -13687,6 +13687,20 @@
|
||||
},
|
||||
"required": ["slug"]
|
||||
},
|
||||
"LocationDefaultFieldInput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"example": "location",
|
||||
"description": "only allowed value for type is `location`. This booking field is displayed only when event type has 2 or more locations in order to allow person doing the booking pick the location."
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["slug"]
|
||||
},
|
||||
"NotesDefaultFieldInput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -13871,6 +13885,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -14429,6 +14446,9 @@
|
||||
"hidden": {
|
||||
"type": "boolean",
|
||||
"description": "If true show under event type settings but don't show this booking field in the Booker. If false show in both."
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["isDefault", "slug", "type", "required", "hidden"]
|
||||
@@ -14438,7 +14458,7 @@
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": ["name", "email", "title", "notes", "guests"],
|
||||
"enum": ["title", "location", "notes", "guests", "rescheduleReason"],
|
||||
"example": "rescheduleReason",
|
||||
"description": "only allowed value for type is `rescheduleReason`",
|
||||
"default": "rescheduleReason"
|
||||
@@ -14478,7 +14498,7 @@
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": ["name", "email", "title", "notes", "guests"],
|
||||
"enum": ["title", "location", "notes", "guests", "rescheduleReason"],
|
||||
"example": "title",
|
||||
"description": "only allowed value for type is `title`",
|
||||
"default": "title"
|
||||
@@ -14518,7 +14538,7 @@
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": ["name", "email", "title", "notes", "guests"],
|
||||
"enum": ["title", "location", "notes", "guests", "rescheduleReason"],
|
||||
"example": "notes",
|
||||
"description": "only allowed value for type is `notes`",
|
||||
"default": "notes"
|
||||
@@ -14558,7 +14578,7 @@
|
||||
"properties": {
|
||||
"slug": {
|
||||
"type": "string",
|
||||
"enum": ["name", "email", "title", "notes", "guests"],
|
||||
"enum": ["title", "location", "notes", "guests", "rescheduleReason"],
|
||||
"example": "guests",
|
||||
"description": "only allowed value for type is `guests`",
|
||||
"default": "guests"
|
||||
@@ -15656,6 +15676,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -17205,6 +17228,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
@@ -17996,6 +18022,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/TitleDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/LocationDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/NotesDefaultFieldInput_2024_06_14"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type {
|
||||
InputBookingField_2024_06_14,
|
||||
LocationDefaultFieldOutput_2024_06_14,
|
||||
PhoneDefaultFieldOutput_2024_06_14,
|
||||
MultiSelectFieldInput_2024_06_14,
|
||||
CheckboxGroupFieldInput_2024_06_14,
|
||||
@@ -8,6 +7,7 @@ import type {
|
||||
NameDefaultFieldInput_2024_06_14,
|
||||
EmailDefaultFieldInput_2024_06_14,
|
||||
TitleDefaultFieldInput_2024_06_14,
|
||||
LocationDefaultFieldInput_2024_06_14,
|
||||
NotesDefaultFieldInput_2024_06_14,
|
||||
GuestsDefaultFieldInput_2024_06_14,
|
||||
RescheduleReasonDefaultFieldInput_2024_06_14,
|
||||
@@ -28,10 +28,7 @@ import {
|
||||
systemBeforeFieldNameSplit,
|
||||
} from "../internal-to-api";
|
||||
|
||||
type InputBookingField =
|
||||
| InputBookingField_2024_06_14
|
||||
| LocationDefaultFieldOutput_2024_06_14
|
||||
| PhoneDefaultFieldOutput_2024_06_14;
|
||||
type InputBookingField = InputBookingField_2024_06_14 | PhoneDefaultFieldOutput_2024_06_14;
|
||||
|
||||
export function transformBookingFieldsApiToInternal(bookingFields: InputBookingField[]) {
|
||||
const customBookingFields = bookingFields.map((field) => {
|
||||
@@ -77,8 +74,7 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
|
||||
if (fieldIsDefaultSystemLocation(field)) {
|
||||
return {
|
||||
...systemBeforeFieldLocation,
|
||||
required: field.required,
|
||||
hidden: field.hidden,
|
||||
label: field.label,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,7 +153,7 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
|
||||
required: !!field.required,
|
||||
hidden: !!field.hidden,
|
||||
label: field.label,
|
||||
placeholder: "placeholder" in field ? field.placeholder : "",
|
||||
placeholder: "placeholder" in field ? field.placeholder : undefined,
|
||||
disableOnPrefill: !!field.disableOnPrefill,
|
||||
};
|
||||
}
|
||||
@@ -168,7 +164,7 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
|
||||
required: !!field.required,
|
||||
hidden: !!field.hidden,
|
||||
label: field.label,
|
||||
placeholder: "placeholder" in field ? field.placeholder : "",
|
||||
placeholder: "placeholder" in field ? field.placeholder : undefined,
|
||||
disableOnPrefill: !!field.disableOnPrefill,
|
||||
};
|
||||
}
|
||||
@@ -179,7 +175,7 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
|
||||
required: !!field.required,
|
||||
hidden: !!field.hidden,
|
||||
label: field.label,
|
||||
placeholder: "placeholder" in field ? field.placeholder : "",
|
||||
placeholder: "placeholder" in field ? field.placeholder : undefined,
|
||||
disableOnPrefill: !!field.disableOnPrefill,
|
||||
};
|
||||
}
|
||||
@@ -190,7 +186,7 @@ function getBaseProperties(field: InputBookingField): CustomField | SystemField
|
||||
required: !!field.required,
|
||||
hidden: !!field.hidden,
|
||||
label: field.label,
|
||||
placeholder: "placeholder" in field ? field.placeholder : "",
|
||||
placeholder: "placeholder" in field ? field.placeholder : undefined,
|
||||
disableOnPrefill: !!field.disableOnPrefill,
|
||||
};
|
||||
}
|
||||
@@ -298,7 +294,7 @@ function fieldIsDefaultAttendeePhone(field: InputBookingField): field is PhoneDe
|
||||
|
||||
function fieldIsDefaultSystemLocation(
|
||||
field: InputBookingField
|
||||
): field is LocationDefaultFieldOutput_2024_06_14 {
|
||||
): field is LocationDefaultFieldInput_2024_06_14 {
|
||||
return "slug" in field && field.slug === "location";
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ export function transformBookingFieldsInternalToApi(
|
||||
slug: "location",
|
||||
required: !!field.required,
|
||||
hidden: !!field.hidden,
|
||||
label: field.label,
|
||||
} satisfies LocationDefaultFieldOutput_2024_06_14;
|
||||
case "rescheduleReason":
|
||||
return {
|
||||
|
||||
@@ -7,10 +7,7 @@ Here is the workflow:
|
||||
1. If you change platform libraries for the first time, then run `yarn local` to build them locally for the first time. This will also make v2 api point to the local libraries.
|
||||
2. If you change them for the second time, then run `yarn build:dev` to re-build them.
|
||||
3. Once you are happy with platform libraries:
|
||||
- run `yarn publish` - it will check "@calcom/platform-libraries" version in npm and update it's package.json to the next version and then it will publish the package to np.
|
||||
- run `yarn postpublish` - it will update the version of "@calcom/platform-libraries" in the api v2 package.json, reset "@calcom/platform-libraries" to 0.0.0 and run yarn install.
|
||||
|
||||
note(Lauris) - we could have 1 publish script but the problem is that `yarn publish` does not exit for some reason.
|
||||
- run `yarn publish-npm` - it will check "@calcom/platform-libraries" version in npm and update it's package.json to the next version and then it will publish the package to npm, update the version of "@calcom/platform-libraries" in the api v2 package.json, reset "@calcom/platform-libraries" to 0.0.0 and run yarn install.
|
||||
|
||||
# Before Merging to main
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
"watch-lru-fix": "watch -n 1 'sed -i'' -e \"s/const CACHE = new lruCache\\.LRUCache({ max: 1e3 });/const CACHE = new lruCache({ max: 1e3 });/g\" ./dist/index.cjs'",
|
||||
"build:dev": "yarn vite build && sed -i'' -e 's/const CACHE = new lruCache\\.LRUCache({ max: 1e3 });/const CACHE = new lruCache({ max: 1e3 });/g' ./dist/index.cjs",
|
||||
"local": "node scripts/local.js && rm -rf dist && yarn build:dev && cd ../../.. && yarn",
|
||||
"publish": "yarn && node scripts/prepublish.js && rm -rf dist && yarn build && npm publish --access public",
|
||||
"postpublish": "node scripts/postpublish.js"
|
||||
"publish-npm": "yarn && node scripts/prepublish.js && rm -rf dist && yarn build && npm publish --access public && node scripts/postpublish.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@calcom/features": "*",
|
||||
|
||||
@@ -3,9 +3,13 @@ import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
import { getCurrentVersion } from "./prepublish.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
main();
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// Get the published version before resetting
|
||||
@@ -14,6 +18,9 @@ async function main() {
|
||||
const librariesPackageJson = JSON.parse(fs.readFileSync(librariesPackageJsonPath, "utf8"));
|
||||
const publishedVersion = librariesPackageJson.version;
|
||||
|
||||
// Wait for the npm registry to reflect our published version
|
||||
await waitForNewestNpmRelease(publishedVersion);
|
||||
|
||||
// Reset libraries package.json version to 0.0.0
|
||||
librariesPackageJson.version = "0.0.0";
|
||||
fs.writeFileSync(librariesPackageJsonPath, `${JSON.stringify(librariesPackageJson, null, 2)}\n`);
|
||||
@@ -55,4 +62,36 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
async function waitForNewestNpmRelease(publishedVersion) {
|
||||
console.log(`Waiting for npm registry to update with version ${publishedVersion}...`);
|
||||
let npmVersion;
|
||||
let attempts = 0;
|
||||
const maxAttempts = 12;
|
||||
|
||||
while (true) {
|
||||
attempts++;
|
||||
npmVersion = await getCurrentVersion();
|
||||
|
||||
if (publishedVersion === npmVersion) {
|
||||
console.log(
|
||||
`Version match confirmed (${publishedVersion}) after ${attempts} attempts. Proceeding with updates...`
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if (attempts >= maxAttempts) {
|
||||
console.log(
|
||||
`Reached maximum attempts (${maxAttempts}). Latest npm version: ${npmVersion}, local version: ${publishedVersion}`
|
||||
);
|
||||
console.log("Proceeding with updates anyway...");
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Attempt ${attempts}/${maxAttempts}: npm version (${npmVersion}) doesn't match local version (${publishedVersion}) yet. Retrying in 5 seconds...`
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
}
|
||||
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// Fetch current version from npm registry
|
||||
function getCurrentVersion() {
|
||||
export function getCurrentVersion() {
|
||||
return new Promise((resolve, reject) => {
|
||||
https
|
||||
.get(
|
||||
|
||||
+30
-55
@@ -22,7 +22,7 @@ const inputBookingFieldTypes = [
|
||||
"url",
|
||||
] as const;
|
||||
|
||||
const inputBookingFieldSlugs = ["name", "email", "title", "notes", "guests"] as const;
|
||||
const inputBookingFieldSlugs = ["title", "location", "notes", "guests", "rescheduleReason"] as const;
|
||||
|
||||
export class NameDefaultFieldInput_2024_06_14 {
|
||||
@IsIn(inputBookingFieldTypes)
|
||||
@@ -189,6 +189,21 @@ export class TitleDefaultFieldInput_2024_06_14 {
|
||||
disableOnPrefill?: boolean;
|
||||
}
|
||||
|
||||
export class LocationDefaultFieldInput_2024_06_14 {
|
||||
@IsIn(inputBookingFieldSlugs)
|
||||
@DocsProperty({
|
||||
example: "location",
|
||||
description:
|
||||
"only allowed value for type is `location`. This booking field is displayed only when event type has 2 or more locations in order to allow person doing the booking pick the location.",
|
||||
})
|
||||
slug!: "location";
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@DocsPropertyOptional()
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export class NotesDefaultFieldInput_2024_06_14 {
|
||||
@IsIn(inputBookingFieldSlugs)
|
||||
@DocsProperty({ example: "notes", description: "only allowed value for type is `notes`" })
|
||||
@@ -865,6 +880,7 @@ type InputDefaultField_2024_06_14 =
|
||||
| SplitNameDefaultFieldInput_2024_06_14
|
||||
| EmailDefaultFieldInput_2024_06_14
|
||||
| TitleDefaultFieldInput_2024_06_14
|
||||
| LocationDefaultFieldInput_2024_06_14
|
||||
| NotesDefaultFieldInput_2024_06_14
|
||||
| GuestsDefaultFieldInput_2024_06_14
|
||||
| RescheduleReasonDefaultFieldInput_2024_06_14;
|
||||
@@ -891,6 +907,7 @@ class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterf
|
||||
splitName: SplitNameDefaultFieldInput_2024_06_14,
|
||||
email: EmailDefaultFieldInput_2024_06_14,
|
||||
title: TitleDefaultFieldInput_2024_06_14,
|
||||
location: LocationDefaultFieldInput_2024_06_14,
|
||||
notes: NotesDefaultFieldInput_2024_06_14,
|
||||
guests: GuestsDefaultFieldInput_2024_06_14,
|
||||
rescheduleReason: RescheduleReasonDefaultFieldInput_2024_06_14,
|
||||
@@ -921,18 +938,22 @@ class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterf
|
||||
for (const field of bookingFields) {
|
||||
const { type, slug } = field;
|
||||
const fieldNeedsType =
|
||||
slug !== "title" && slug !== "notes" && slug !== "guests" && slug !== "rescheduleReason";
|
||||
slug !== "title" &&
|
||||
slug !== "notes" &&
|
||||
slug !== "guests" &&
|
||||
slug !== "rescheduleReason" &&
|
||||
slug !== "location";
|
||||
|
||||
if (fieldNeedsType && !type) {
|
||||
throw new BadRequestException(
|
||||
`All booking fields except ones with slug equal to title, notes, guests and rescheduleReason must have a 'type' property.`
|
||||
`All booking fields except ones with slug equal to title, notes, guests, rescheduleReason and location must have a 'type' property.`
|
||||
);
|
||||
}
|
||||
|
||||
const fieldNeedsSlug = type !== "name" && type !== "splitName" && type !== "email";
|
||||
if (fieldNeedsSlug && !slug) {
|
||||
throw new BadRequestException(
|
||||
`Each booking field except ones with type equal to name and email must have a 'slug' property.`
|
||||
`Each booking field except ones with type equal to name, splitName, email must have a 'slug' property.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -945,10 +966,12 @@ class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterf
|
||||
slugs.push(slug);
|
||||
}
|
||||
|
||||
const ClassType = type ? this.classMap[type] : this.classMap[slug];
|
||||
const ClassType = fieldNeedsType ? this.classMap[type] : this.classMap[slug];
|
||||
if (!ClassType) {
|
||||
throw new BadRequestException(
|
||||
type ? `Unsupported booking field type '${type}'.` : `Unsupported booking field slug '${slug}'.`
|
||||
fieldNeedsType
|
||||
? `Unsupported booking field type '${type}'.`
|
||||
: `Unsupported booking field slug '${slug}'.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -956,7 +979,7 @@ class InputBookingFieldValidator_2024_06_14 implements ValidatorConstraintInterf
|
||||
const errors = await validate(instance);
|
||||
if (errors.length > 0) {
|
||||
const message = errors.flatMap((error) => Object.values(error.constraints || {})).join(", ");
|
||||
throw new BadRequestException(`Validation failed for ${type} booking field: ${message}`);
|
||||
throw new BadRequestException(`Validation failed for ${type || slug} booking field: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,51 +1003,3 @@ export function ValidateInputBookingFields_2024_06_14(validationOptions?: Valida
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function isDefaultField(field: InputBookingField_2024_06_14): field is InputDefaultField_2024_06_14 {
|
||||
if (
|
||||
isDefaultNameField(field) ||
|
||||
isDefaultEmailField(field) ||
|
||||
isDefaultTitleField(field) ||
|
||||
isDefaultNotesField(field) ||
|
||||
isDefaultGuestsField(field) ||
|
||||
isDefaultRescheduleReasonField(field)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isDefaultNameField(field: InputBookingField_2024_06_14): field is NameDefaultFieldInput_2024_06_14 {
|
||||
return ("type" in field && field.type === "name") || ("slug" in field && field.slug === "name");
|
||||
}
|
||||
|
||||
function isDefaultEmailField(
|
||||
field: InputBookingField_2024_06_14
|
||||
): field is EmailDefaultFieldInput_2024_06_14 {
|
||||
return ("type" in field && field.type === "email") || ("slug" in field && field.slug === "email");
|
||||
}
|
||||
|
||||
function isDefaultTitleField(
|
||||
field: InputBookingField_2024_06_14
|
||||
): field is TitleDefaultFieldInput_2024_06_14 {
|
||||
return "slug" in field && field.slug === "title";
|
||||
}
|
||||
|
||||
function isDefaultNotesField(
|
||||
field: InputBookingField_2024_06_14
|
||||
): field is NotesDefaultFieldInput_2024_06_14 {
|
||||
return "slug" in field && field.slug === "notes";
|
||||
}
|
||||
|
||||
function isDefaultGuestsField(
|
||||
field: InputBookingField_2024_06_14
|
||||
): field is GuestsDefaultFieldInput_2024_06_14 {
|
||||
return "slug" in field && field.slug === "guests";
|
||||
}
|
||||
|
||||
function isDefaultRescheduleReasonField(
|
||||
field: InputBookingField_2024_06_14
|
||||
): field is RescheduleReasonDefaultFieldInput_2024_06_14 {
|
||||
return "slug" in field && field.slug === "rescheduleReason";
|
||||
}
|
||||
|
||||
+4
-1
@@ -40,6 +40,7 @@ import {
|
||||
TextAreaFieldInput_2024_06_14,
|
||||
TextFieldInput_2024_06_14,
|
||||
TitleDefaultFieldInput_2024_06_14,
|
||||
LocationDefaultFieldInput_2024_06_14,
|
||||
UrlFieldInput_2024_06_14,
|
||||
} from "./booking-fields.input";
|
||||
import type { InputBookingField_2024_06_14 } from "./booking-fields.input";
|
||||
@@ -117,6 +118,7 @@ export const CREATE_EVENT_SLUG_EXAMPLE = "learn-the-secrets-of-masterchief";
|
||||
NameDefaultFieldInput_2024_06_14,
|
||||
EmailDefaultFieldInput_2024_06_14,
|
||||
TitleDefaultFieldInput_2024_06_14,
|
||||
LocationDefaultFieldInput_2024_06_14,
|
||||
NotesDefaultFieldInput_2024_06_14,
|
||||
GuestsDefaultFieldInput_2024_06_14,
|
||||
RescheduleReasonDefaultFieldInput_2024_06_14,
|
||||
@@ -163,6 +165,7 @@ class BaseCreateEventTypeInput {
|
||||
{ $ref: getSchemaPath(NameDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(EmailDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(TitleDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(LocationDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(NotesDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(GuestsDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(RescheduleReasonDefaultFieldInput_2024_06_14) },
|
||||
@@ -278,7 +281,7 @@ class BaseCreateEventTypeInput {
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Min(0)
|
||||
@DocsPropertyOptional({ description: "Offset timeslots shown to bookers by a specified number of minutes" })
|
||||
offsetStart?: number;
|
||||
|
||||
|
||||
+4
-1
@@ -38,6 +38,7 @@ import {
|
||||
TextAreaFieldInput_2024_06_14,
|
||||
TextFieldInput_2024_06_14,
|
||||
TitleDefaultFieldInput_2024_06_14,
|
||||
LocationDefaultFieldInput_2024_06_14,
|
||||
ValidateInputBookingFields_2024_06_14,
|
||||
} from "./booking-fields.input";
|
||||
import type { BookingLimitsCount_2024_06_14 } from "./booking-limits-count.input";
|
||||
@@ -113,6 +114,7 @@ import { Seats_2024_06_14 } from "./seats.input";
|
||||
NameDefaultFieldInput_2024_06_14,
|
||||
EmailDefaultFieldInput_2024_06_14,
|
||||
TitleDefaultFieldInput_2024_06_14,
|
||||
LocationDefaultFieldInput_2024_06_14,
|
||||
NotesDefaultFieldInput_2024_06_14,
|
||||
GuestsDefaultFieldInput_2024_06_14,
|
||||
RescheduleReasonDefaultFieldInput_2024_06_14
|
||||
@@ -161,6 +163,7 @@ class BaseUpdateEventTypeInput {
|
||||
{ $ref: getSchemaPath(NameDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(EmailDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(TitleDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(LocationDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(NotesDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(GuestsDefaultFieldInput_2024_06_14) },
|
||||
{ $ref: getSchemaPath(RescheduleReasonDefaultFieldInput_2024_06_14) },
|
||||
@@ -275,7 +278,7 @@ class BaseUpdateEventTypeInput {
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Min(0)
|
||||
@DocsPropertyOptional({ description: "Offset timeslots shown to bookers by a specified number of minutes" })
|
||||
offsetStart?: number;
|
||||
|
||||
|
||||
+5
@@ -141,6 +141,11 @@ export class LocationDefaultFieldOutput_2024_06_14 {
|
||||
"If true show under event type settings but don't show this booking field in the Booker. If false show in both.",
|
||||
})
|
||||
hidden!: boolean;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export class RescheduleReasonDefaultFieldOutput_2024_06_14 extends RescheduleReasonDefaultFieldInput_2024_06_14 {
|
||||
|
||||
Reference in New Issue
Block a user