@webiny/webhooks 6.4.1 → 6.4.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import { computed, makeAutoObservable, runInAction } from "mobx";
2
+ import { z } from "zod";
2
3
  import { WebhookFormPresenter } from "./abstractions.js";
3
4
  import { GetWebhookUseCase } from "../../features/getWebhook/abstractions.js";
4
5
  import { CreateWebhookUseCase } from "../../features/createWebhook/abstractions.js";
@@ -48,7 +49,7 @@ class WebhookFormPresenterImpl {
48
49
  slug: fields.text().label("Slug").required("Slug is required").computedUntilDirty((form)=>{
49
50
  const name = String(form.field("name").getValue() ?? "");
50
51
  return name.trim().toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-");
51
- }),
52
+ }).schema(z.string().min(3, "Slug must be at least 3 characters long")),
52
53
  endpointUrl: fields.text().label("Endpoint URL").required("Endpoint URL is required").placeholder("https://"),
53
54
  description: fields.text().label("Description").renderer("textarea"),
54
55
  enabled: fields.boolean().label("Enabled").defaultValue(false)
@@ -1 +1 @@
1
- {"version":3,"file":"admin/presentation/WebhookForm/WebhookFormPresenter.js","sources":["../../../../src/admin/presentation/WebhookForm/WebhookFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { WebhookEvent } from \"~/admin/shared/types.js\";\nimport {\n WebhookFormPresenter as Abstraction,\n type IWebhookFormPresenter,\n type IWebhookFormViewModel\n} from \"./abstractions.js\";\nimport { GetWebhookUseCase } from \"~/admin/features/getWebhook/abstractions.js\";\nimport { CreateWebhookUseCase } from \"~/admin/features/createWebhook/abstractions.js\";\nimport { UpdateWebhookUseCase } from \"~/admin/features/updateWebhook/abstractions.js\";\nimport { DeleteWebhookUseCase } from \"~/admin/features/deleteWebhook/abstractions.js\";\nimport { ListAvailableEventsUseCase } from \"~/admin/features/listAvailableEvents/abstractions.js\";\nimport { WebhookPermissions } from \"~/admin/features/permissions/abstractions.js\";\nimport {\n FormModelFactory,\n type IFormModel,\n type ILayoutNodeBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nclass WebhookFormPresenterImpl implements IWebhookFormPresenter {\n private _loading = false;\n private _saving = false;\n private _isNew = false;\n private _webhook: Webhook | null = null;\n private _webhookId: string | null = null;\n private _form: IFormModel;\n private _entityFieldNames: string[] = [];\n private _entityGroups: Map<string, Map<string, WebhookEvent[]>> = new Map();\n\n public get vm(): IWebhookFormViewModel {\n return {\n loading: this._loading,\n saving: this._saving,\n isNew: this._isNew,\n webhook: this._webhook,\n permissions: {\n canEdit: this.permissions.canEdit(\"webhook\"),\n canDelete: this.permissions.canDelete(\"webhook\")\n },\n form: this._form.vm\n };\n }\n\n public constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly getWebhookUseCase: GetWebhookUseCase.Interface,\n private readonly createWebhookUseCase: CreateWebhookUseCase.Interface,\n private readonly updateWebhookUseCase: UpdateWebhookUseCase.Interface,\n private readonly deleteWebhookUseCase: DeleteWebhookUseCase.Interface,\n private readonly listAvailableEventsUseCase: ListAvailableEventsUseCase.Interface,\n private readonly permissions: WebhookPermissions.Interface\n ) {\n this._form = this.buildForm();\n\n makeAutoObservable(this, { vm: computed });\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(form => {\n const name = String(form.field(\"name\").getValue() ?? \"\");\n return name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n }),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required(\"Endpoint URL is required\")\n .placeholder(\"https://\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ]\n });\n }\n\n private entityFieldName(appLabel: string, entityLabel: string): string {\n const slug = `${appLabel}_${entityLabel}`\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_|_$/g, \"\");\n return `events_${slug}`;\n }\n\n private addEventFields(events: WebhookEvent[]): void {\n const grouped = new Map<string, Map<string, WebhookEvent[]>>();\n for (const event of events) {\n let appMap = grouped.get(event.appLabel);\n if (!appMap) {\n appMap = new Map();\n grouped.set(event.appLabel, appMap);\n }\n const existing = appMap.get(event.entityLabel) ?? [];\n existing.push(event);\n appMap.set(event.entityLabel, existing);\n }\n\n this._entityGroups = grouped;\n this._entityFieldNames = [];\n\n this._form.fields(fields => {\n const result: Record<string, ReturnType<typeof fields.object>> = {};\n\n for (const [appLabel, entities] of grouped) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n this._entityFieldNames.push(fieldName);\n\n result[fieldName] = fields\n .object()\n .label(entityLabel)\n .renderer(\"objectAccordionSingle\", { open: false })\n .fields(f => {\n return {\n selected: f\n .text()\n .list()\n .options(\n entityEvents.map(e => ({\n label: e.label,\n value: e.eventName\n }))\n )\n .renderer(\"checkboxes\")\n };\n });\n }\n }\n\n return result;\n });\n\n this._form.setLayout(layout => {\n const rows: ILayoutNodeBuilder[] = [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ];\n\n for (const [appLabel, entities] of grouped) {\n rows.push(layout.separator());\n rows.push(layout.element(\"sectionHeading\", { label: appLabel }));\n\n for (const [entityLabel] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n rows.push(layout.object(fieldName, inner => [inner.row(\"selected\")]));\n }\n }\n\n return rows;\n });\n\n this._form.addRule(form => {\n if (this._entityFieldNames.length === 0) {\n return [];\n }\n for (const fieldName of this._entityFieldNames) {\n const objectField = form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n return [];\n }\n }\n\n return [{ path: \"Events\", message: \"At least one event must be selected.\" }];\n });\n }\n\n private collectEvents(): string[] {\n const allEvents: string[] = [];\n\n for (const fieldName of this._entityFieldNames) {\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n allEvents.push(...values);\n }\n }\n\n return allEvents;\n }\n\n private distributeEvents(webhookEvents: string[]): void {\n const eventSet = new Set(webhookEvents);\n\n for (const [appLabel, entities] of this._entityGroups) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n\n const selected = entityEvents\n .filter(e => eventSet.has(e.eventName))\n .map(e => e.eventName);\n selectedField.setValue(selected);\n }\n }\n }\n\n public async save(): Promise<boolean> {\n const data = await this._form.submit<Record<string, unknown>>();\n if (data === false) {\n return false;\n }\n\n runInAction(() => {\n this._saving = true;\n });\n\n try {\n const merged = {\n name: data.name as string,\n slug: data.slug as string,\n endpointUrl: data.endpointUrl as string,\n description: (data.description as string) || undefined,\n enabled: data.enabled as boolean,\n events: this.collectEvents()\n };\n\n if (this._isNew) {\n const created = await this.createWebhookUseCase.execute(merged);\n\n runInAction(() => {\n this._webhook = created;\n this._webhookId = created.id;\n this._isNew = false;\n this._form.field(\"slug\").setDisabled(true);\n });\n } else {\n const updated = await this.updateWebhookUseCase.execute(this._webhookId!, merged);\n\n runInAction(() => {\n this._webhook = updated;\n });\n }\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n\n return true;\n }\n\n public async deleteWebhook(): Promise<void> {\n if (!this._webhookId || this._isNew) {\n return;\n }\n await this.deleteWebhookUseCase.execute(this._webhookId);\n }\n\n public async init(id: string): Promise<void> {\n this._loading = true;\n this._isNew = id === \"new\";\n this._webhookId = id === \"new\" ? null : id;\n\n const eventsPromise = this.listAvailableEventsUseCase.execute();\n\n if (!this._isNew) {\n const [webhook, events] = await Promise.all([\n this.getWebhookUseCase.execute(id),\n eventsPromise\n ]);\n\n runInAction(() => {\n this._webhook = webhook;\n this._form = this.buildForm();\n this.addEventFields(events);\n this._form.setData({\n name: webhook.name,\n slug: webhook.slug,\n endpointUrl: webhook.endpointUrl,\n description: webhook.description ?? \"\",\n enabled: webhook.enabled\n });\n this._form.field(\"slug\").setDisabled(true);\n this.distributeEvents(webhook.events);\n this._loading = false;\n });\n } else {\n const events = await eventsPromise;\n\n runInAction(() => {\n this._form = this.buildForm();\n this.addEventFields(events);\n this._loading = false;\n });\n }\n }\n}\n\nexport const WebhookFormPresenter = Abstraction.createImplementation({\n implementation: WebhookFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n GetWebhookUseCase,\n CreateWebhookUseCase,\n UpdateWebhookUseCase,\n DeleteWebhookUseCase,\n ListAvailableEventsUseCase,\n WebhookPermissions\n ]\n});\n"],"names":["WebhookFormPresenterImpl","formModelFactory","getWebhookUseCase","createWebhookUseCase","updateWebhookUseCase","deleteWebhookUseCase","listAvailableEventsUseCase","permissions","Map","makeAutoObservable","computed","fields","form","name","String","layout","appLabel","entityLabel","slug","events","grouped","event","appMap","existing","result","entities","entityEvents","fieldName","f","e","rows","inner","objectField","selectedField","values","allEvents","webhookEvents","eventSet","Set","selected","data","runInAction","merged","undefined","created","updated","id","eventsPromise","webhook","Promise","WebhookFormPresenter","Abstraction","FormModelFactory","GetWebhookUseCase","CreateWebhookUseCase","UpdateWebhookUseCase","DeleteWebhookUseCase","ListAvailableEventsUseCase","WebhookPermissions"],"mappings":"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"}
1
+ {"version":3,"file":"admin/presentation/WebhookForm/WebhookFormPresenter.js","sources":["../../../../src/admin/presentation/WebhookForm/WebhookFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport { z } from \"zod\";\nimport type { Webhook } from \"~/admin/shared/types.js\";\nimport type { WebhookEvent } from \"~/admin/shared/types.js\";\nimport {\n WebhookFormPresenter as Abstraction,\n type IWebhookFormPresenter,\n type IWebhookFormViewModel\n} from \"./abstractions.js\";\nimport { GetWebhookUseCase } from \"~/admin/features/getWebhook/abstractions.js\";\nimport { CreateWebhookUseCase } from \"~/admin/features/createWebhook/abstractions.js\";\nimport { UpdateWebhookUseCase } from \"~/admin/features/updateWebhook/abstractions.js\";\nimport { DeleteWebhookUseCase } from \"~/admin/features/deleteWebhook/abstractions.js\";\nimport { ListAvailableEventsUseCase } from \"~/admin/features/listAvailableEvents/abstractions.js\";\nimport { WebhookPermissions } from \"~/admin/features/permissions/abstractions.js\";\nimport {\n FormModelFactory,\n type IFormModel,\n type ILayoutNodeBuilder\n} from \"@webiny/app-admin/features/formModel/abstractions.js\";\n\nclass WebhookFormPresenterImpl implements IWebhookFormPresenter {\n private _loading = false;\n private _saving = false;\n private _isNew = false;\n private _webhook: Webhook | null = null;\n private _webhookId: string | null = null;\n private _form: IFormModel;\n private _entityFieldNames: string[] = [];\n private _entityGroups: Map<string, Map<string, WebhookEvent[]>> = new Map();\n\n public get vm(): IWebhookFormViewModel {\n return {\n loading: this._loading,\n saving: this._saving,\n isNew: this._isNew,\n webhook: this._webhook,\n permissions: {\n canEdit: this.permissions.canEdit(\"webhook\"),\n canDelete: this.permissions.canDelete(\"webhook\")\n },\n form: this._form.vm\n };\n }\n\n public constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly getWebhookUseCase: GetWebhookUseCase.Interface,\n private readonly createWebhookUseCase: CreateWebhookUseCase.Interface,\n private readonly updateWebhookUseCase: UpdateWebhookUseCase.Interface,\n private readonly deleteWebhookUseCase: DeleteWebhookUseCase.Interface,\n private readonly listAvailableEventsUseCase: ListAvailableEventsUseCase.Interface,\n private readonly permissions: WebhookPermissions.Interface\n ) {\n this._form = this.buildForm();\n\n makeAutoObservable(this, { vm: computed });\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(form => {\n const name = String(form.field(\"name\").getValue() ?? \"\");\n return name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\");\n })\n .schema(z.string().min(3, \"Slug must be at least 3 characters long\")),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required(\"Endpoint URL is required\")\n .placeholder(\"https://\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ]\n });\n }\n\n private entityFieldName(appLabel: string, entityLabel: string): string {\n const slug = `${appLabel}_${entityLabel}`\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_|_$/g, \"\");\n return `events_${slug}`;\n }\n\n private addEventFields(events: WebhookEvent[]): void {\n const grouped = new Map<string, Map<string, WebhookEvent[]>>();\n for (const event of events) {\n let appMap = grouped.get(event.appLabel);\n if (!appMap) {\n appMap = new Map();\n grouped.set(event.appLabel, appMap);\n }\n const existing = appMap.get(event.entityLabel) ?? [];\n existing.push(event);\n appMap.set(event.entityLabel, existing);\n }\n\n this._entityGroups = grouped;\n this._entityFieldNames = [];\n\n this._form.fields(fields => {\n const result: Record<string, ReturnType<typeof fields.object>> = {};\n\n for (const [appLabel, entities] of grouped) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n this._entityFieldNames.push(fieldName);\n\n result[fieldName] = fields\n .object()\n .label(entityLabel)\n .renderer(\"objectAccordionSingle\", { open: false })\n .fields(f => {\n return {\n selected: f\n .text()\n .list()\n .options(\n entityEvents.map(e => ({\n label: e.label,\n value: e.eventName\n }))\n )\n .renderer(\"checkboxes\")\n };\n });\n }\n }\n\n return result;\n });\n\n this._form.setLayout(layout => {\n const rows: ILayoutNodeBuilder[] = [\n layout.row(\"name\", \"slug\"),\n layout.row(\"endpointUrl\"),\n layout.row(\"description\"),\n layout.row(\"enabled\")\n ];\n\n for (const [appLabel, entities] of grouped) {\n rows.push(layout.separator());\n rows.push(layout.element(\"sectionHeading\", { label: appLabel }));\n\n for (const [entityLabel] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n rows.push(layout.object(fieldName, inner => [inner.row(\"selected\")]));\n }\n }\n\n return rows;\n });\n\n this._form.addRule(form => {\n if (this._entityFieldNames.length === 0) {\n return [];\n }\n for (const fieldName of this._entityFieldNames) {\n const objectField = form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n return [];\n }\n }\n\n return [{ path: \"Events\", message: \"At least one event must be selected.\" }];\n });\n }\n\n private collectEvents(): string[] {\n const allEvents: string[] = [];\n\n for (const fieldName of this._entityFieldNames) {\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n const values = selectedField.getValue<string[]>();\n if (values && values.length > 0) {\n allEvents.push(...values);\n }\n }\n\n return allEvents;\n }\n\n private distributeEvents(webhookEvents: string[]): void {\n const eventSet = new Set(webhookEvents);\n\n for (const [appLabel, entities] of this._entityGroups) {\n for (const [entityLabel, entityEvents] of entities) {\n const fieldName = this.entityFieldName(appLabel, entityLabel);\n const objectField = this._form.field(fieldName).as(\"object\");\n const selectedField = objectField.children.get(\"selected\");\n if (!selectedField) {\n continue;\n }\n\n const selected = entityEvents\n .filter(e => eventSet.has(e.eventName))\n .map(e => e.eventName);\n selectedField.setValue(selected);\n }\n }\n }\n\n public async save(): Promise<boolean> {\n const data = await this._form.submit<Record<string, unknown>>();\n if (data === false) {\n return false;\n }\n\n runInAction(() => {\n this._saving = true;\n });\n\n try {\n const merged = {\n name: data.name as string,\n slug: data.slug as string,\n endpointUrl: data.endpointUrl as string,\n description: (data.description as string) || undefined,\n enabled: data.enabled as boolean,\n events: this.collectEvents()\n };\n\n if (this._isNew) {\n const created = await this.createWebhookUseCase.execute(merged);\n\n runInAction(() => {\n this._webhook = created;\n this._webhookId = created.id;\n this._isNew = false;\n this._form.field(\"slug\").setDisabled(true);\n });\n } else {\n const updated = await this.updateWebhookUseCase.execute(this._webhookId!, merged);\n\n runInAction(() => {\n this._webhook = updated;\n });\n }\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n\n return true;\n }\n\n public async deleteWebhook(): Promise<void> {\n if (!this._webhookId || this._isNew) {\n return;\n }\n await this.deleteWebhookUseCase.execute(this._webhookId);\n }\n\n public async init(id: string): Promise<void> {\n this._loading = true;\n this._isNew = id === \"new\";\n this._webhookId = id === \"new\" ? null : id;\n\n const eventsPromise = this.listAvailableEventsUseCase.execute();\n\n if (!this._isNew) {\n const [webhook, events] = await Promise.all([\n this.getWebhookUseCase.execute(id),\n eventsPromise\n ]);\n\n runInAction(() => {\n this._webhook = webhook;\n this._form = this.buildForm();\n this.addEventFields(events);\n this._form.setData({\n name: webhook.name,\n slug: webhook.slug,\n endpointUrl: webhook.endpointUrl,\n description: webhook.description ?? \"\",\n enabled: webhook.enabled\n });\n this._form.field(\"slug\").setDisabled(true);\n this.distributeEvents(webhook.events);\n this._loading = false;\n });\n } else {\n const events = await eventsPromise;\n\n runInAction(() => {\n this._form = this.buildForm();\n this.addEventFields(events);\n this._loading = false;\n });\n }\n }\n}\n\nexport const WebhookFormPresenter = Abstraction.createImplementation({\n implementation: WebhookFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n GetWebhookUseCase,\n CreateWebhookUseCase,\n UpdateWebhookUseCase,\n DeleteWebhookUseCase,\n ListAvailableEventsUseCase,\n WebhookPermissions\n ]\n});\n"],"names":["WebhookFormPresenterImpl","formModelFactory","getWebhookUseCase","createWebhookUseCase","updateWebhookUseCase","deleteWebhookUseCase","listAvailableEventsUseCase","permissions","Map","makeAutoObservable","computed","fields","form","name","String","z","layout","appLabel","entityLabel","slug","events","grouped","event","appMap","existing","result","entities","entityEvents","fieldName","f","e","rows","inner","objectField","selectedField","values","allEvents","webhookEvents","eventSet","Set","selected","data","runInAction","merged","undefined","created","updated","id","eventsPromise","webhook","Promise","WebhookFormPresenter","Abstraction","FormModelFactory","GetWebhookUseCase","CreateWebhookUseCase","UpdateWebhookUseCase","DeleteWebhookUseCase","ListAvailableEventsUseCase","WebhookPermissions"],"mappings":"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"}
@@ -11,7 +11,7 @@ class WebhookModelFactory {
11
11
  "$hidden:true"
12
12
  ]);
13
13
  model.fields((fields)=>({
14
- name: fields.text().label("Name").required().minLength(8, "Name must be at least 8 characters long."),
14
+ name: fields.text().label("Name").required(),
15
15
  slug: fields.text().label("Slug").required().description("URL-safe identifier, unique per tenant.").minLength(3, "Slug must be at least 3 characters long.").pattern("^[a-z0-9]+(?:-[a-z0-9]+)*$", "", "Slug can only contain lowercase letters, numbers, and hyphens, and must start and end with a letter or number."),
16
16
  endpointUrl: fields.text().label("Endpoint URL").required().description("HTTPS destination for POST requests.").url("Must be a valid URL starting with https://").minLength(8, "Endpoint URL must be at least 8 characters long.").pattern("^(https:\\/\\/.+|http:\\/\\/localhost.*)", "", "Endpoint URL must start with https://"),
17
17
  description: fields.longText().label("Description"),
@@ -1 +1 @@
1
- {"version":3,"file":"api/models/WebhookModel.js","sources":["../../../src/api/models/WebhookModel.ts"],"sourcesContent":["import { ModelFactory } from \"@webiny/api-headless-cms/features/modelBuilder/index.js\";\nimport { WEBHOOK_MODEL_ID } from \"~/api/domain/constants.js\";\n\nclass WebhookModelFactory implements ModelFactory.Interface {\n async execute(builder: ModelFactory.Builder) {\n const model = builder\n .public({ modelId: WEBHOOK_MODEL_ID, name: \"Webhook\", group: \"hidden\" })\n .description(\"Stores webhook configurations.\")\n .titleFieldId(\"name\")\n .singularApiName(\"Webhook\")\n .pluralApiName(\"Webhooks\")\n .tags([\"$publishing:false\", \"$hidden:true\"]);\n\n model.fields(fields => ({\n name: fields\n .text()\n .label(\"Name\")\n .required()\n .minLength(8, \"Name must be at least 8 characters long.\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required()\n .description(\"URL-safe identifier, unique per tenant.\")\n .minLength(3, \"Slug must be at least 3 characters long.\")\n .pattern(\n \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n \"\",\n \"Slug can only contain lowercase letters, numbers, and hyphens, and must start and end with a letter or number.\"\n ),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required()\n .description(\"HTTPS destination for POST requests.\")\n .url(\"Must be a valid URL starting with https://\")\n .minLength(8, \"Endpoint URL must be at least 8 characters long.\")\n .pattern(\n \"^(https:\\\\/\\\\/.+|http:\\\\/\\\\/localhost.*)\",\n \"\",\n \"Endpoint URL must start with https://\"\n ),\n description: fields.longText().label(\"Description\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false),\n events: fields\n .text()\n .list()\n .label(\"Events\")\n .defaultValue([])\n .listMinLength(1, \"At least one event must be selected.\"),\n signingSecret: fields\n .text()\n .encrypt()\n .label(\"Signing Secret\")\n .description(\"Signing secret - will be encrypted in the database.\")\n }));\n\n return [model];\n }\n}\n\nexport const WebhookModel = ModelFactory.createImplementation({\n implementation: WebhookModelFactory,\n dependencies: []\n});\n"],"names":["WebhookModelFactory","builder","model","WEBHOOK_MODEL_ID","fields","WebhookModel","ModelFactory"],"mappings":";;AAGA,MAAMA;IACF,MAAM,QAAQC,OAA6B,EAAE;QACzC,MAAMC,QAAQD,QACT,MAAM,CAAC;YAAE,SAASE;YAAkB,MAAM;YAAW,OAAO;QAAS,GACrE,WAAW,CAAC,kCACZ,YAAY,CAAC,QACb,eAAe,CAAC,WAChB,aAAa,CAAC,YACd,IAAI,CAAC;YAAC;YAAqB;SAAe;QAE/CD,MAAM,MAAM,CAACE,CAAAA,SAAW;gBACpB,MAAMA,OACD,IAAI,GACJ,KAAK,CAAC,QACN,QAAQ,GACR,SAAS,CAAC,GAAG;gBAClB,MAAMA,OACD,IAAI,GACJ,KAAK,CAAC,QACN,QAAQ,GACR,WAAW,CAAC,2CACZ,SAAS,CAAC,GAAG,4CACb,OAAO,CACJ,8BACA,IACA;gBAER,aAAaA,OACR,IAAI,GACJ,KAAK,CAAC,gBACN,QAAQ,GACR,WAAW,CAAC,wCACZ,GAAG,CAAC,8CACJ,SAAS,CAAC,GAAG,oDACb,OAAO,CACJ,4CACA,IACA;gBAER,aAAaA,OAAO,QAAQ,GAAG,KAAK,CAAC;gBACrC,SAASA,OAAO,OAAO,GAAG,KAAK,CAAC,WAAW,YAAY,CAAC;gBACxD,QAAQA,OACH,IAAI,GACJ,IAAI,GACJ,KAAK,CAAC,UACN,YAAY,CAAC,EAAE,EACf,aAAa,CAAC,GAAG;gBACtB,eAAeA,OACV,IAAI,GACJ,OAAO,GACP,KAAK,CAAC,kBACN,WAAW,CAAC;YACrB;QAEA,OAAO;YAACF;SAAM;IAClB;AACJ;AAEO,MAAMG,eAAeC,aAAa,oBAAoB,CAAC;IAC1D,gBAAgBN;IAChB,cAAc,EAAE;AACpB"}
1
+ {"version":3,"file":"api/models/WebhookModel.js","sources":["../../../src/api/models/WebhookModel.ts"],"sourcesContent":["import { ModelFactory } from \"@webiny/api-headless-cms/features/modelBuilder/index.js\";\nimport { WEBHOOK_MODEL_ID } from \"~/api/domain/constants.js\";\n\nclass WebhookModelFactory implements ModelFactory.Interface {\n async execute(builder: ModelFactory.Builder) {\n const model = builder\n .public({ modelId: WEBHOOK_MODEL_ID, name: \"Webhook\", group: \"hidden\" })\n .description(\"Stores webhook configurations.\")\n .titleFieldId(\"name\")\n .singularApiName(\"Webhook\")\n .pluralApiName(\"Webhooks\")\n .tags([\"$publishing:false\", \"$hidden:true\"]);\n\n model.fields(fields => ({\n name: fields.text().label(\"Name\").required(),\n slug: fields\n .text()\n .label(\"Slug\")\n .required()\n .description(\"URL-safe identifier, unique per tenant.\")\n .minLength(3, \"Slug must be at least 3 characters long.\")\n .pattern(\n \"^[a-z0-9]+(?:-[a-z0-9]+)*$\",\n \"\",\n \"Slug can only contain lowercase letters, numbers, and hyphens, and must start and end with a letter or number.\"\n ),\n endpointUrl: fields\n .text()\n .label(\"Endpoint URL\")\n .required()\n .description(\"HTTPS destination for POST requests.\")\n .url(\"Must be a valid URL starting with https://\")\n .minLength(8, \"Endpoint URL must be at least 8 characters long.\")\n .pattern(\n \"^(https:\\\\/\\\\/.+|http:\\\\/\\\\/localhost.*)\",\n \"\",\n \"Endpoint URL must start with https://\"\n ),\n description: fields.longText().label(\"Description\"),\n enabled: fields.boolean().label(\"Enabled\").defaultValue(false),\n events: fields\n .text()\n .list()\n .label(\"Events\")\n .defaultValue([])\n .listMinLength(1, \"At least one event must be selected.\"),\n signingSecret: fields\n .text()\n .encrypt()\n .label(\"Signing Secret\")\n .description(\"Signing secret - will be encrypted in the database.\")\n }));\n\n return [model];\n }\n}\n\nexport const WebhookModel = ModelFactory.createImplementation({\n implementation: WebhookModelFactory,\n dependencies: []\n});\n"],"names":["WebhookModelFactory","builder","model","WEBHOOK_MODEL_ID","fields","WebhookModel","ModelFactory"],"mappings":";;AAGA,MAAMA;IACF,MAAM,QAAQC,OAA6B,EAAE;QACzC,MAAMC,QAAQD,QACT,MAAM,CAAC;YAAE,SAASE;YAAkB,MAAM;YAAW,OAAO;QAAS,GACrE,WAAW,CAAC,kCACZ,YAAY,CAAC,QACb,eAAe,CAAC,WAChB,aAAa,CAAC,YACd,IAAI,CAAC;YAAC;YAAqB;SAAe;QAE/CD,MAAM,MAAM,CAACE,CAAAA,SAAW;gBACpB,MAAMA,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAQ;gBAC1C,MAAMA,OACD,IAAI,GACJ,KAAK,CAAC,QACN,QAAQ,GACR,WAAW,CAAC,2CACZ,SAAS,CAAC,GAAG,4CACb,OAAO,CACJ,8BACA,IACA;gBAER,aAAaA,OACR,IAAI,GACJ,KAAK,CAAC,gBACN,QAAQ,GACR,WAAW,CAAC,wCACZ,GAAG,CAAC,8CACJ,SAAS,CAAC,GAAG,oDACb,OAAO,CACJ,4CACA,IACA;gBAER,aAAaA,OAAO,QAAQ,GAAG,KAAK,CAAC;gBACrC,SAASA,OAAO,OAAO,GAAG,KAAK,CAAC,WAAW,YAAY,CAAC;gBACxD,QAAQA,OACH,IAAI,GACJ,IAAI,GACJ,KAAK,CAAC,UACN,YAAY,CAAC,EAAE,EACf,aAAa,CAAC,GAAG;gBACtB,eAAeA,OACV,IAAI,GACJ,OAAO,GACP,KAAK,CAAC,kBACN,WAAW,CAAC;YACrB;QAEA,OAAO;YAACF;SAAM;IAClB;AACJ;AAEO,MAAMG,eAAeC,aAAa,oBAAoB,CAAC;IAC1D,gBAAgBN;IAChB,cAAc,EAAE;AACpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/webhooks",
3
- "version": "6.4.1",
3
+ "version": "6.4.2-beta.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -19,17 +19,17 @@
19
19
  },
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@webiny/admin-ui": "6.4.1",
23
- "@webiny/api-core": "6.4.1",
24
- "@webiny/api-headless-cms": "6.4.1",
25
- "@webiny/app": "6.4.1",
26
- "@webiny/app-admin": "6.4.1",
27
- "@webiny/background-tasks": "6.4.1",
28
- "@webiny/feature": "6.4.1",
29
- "@webiny/handler-graphql": "6.4.1",
30
- "@webiny/icons": "6.4.1",
31
- "@webiny/sdk": "6.4.1",
32
- "@webiny/utils": "6.4.1",
22
+ "@webiny/admin-ui": "6.4.2-beta.1",
23
+ "@webiny/api-core": "6.4.2-beta.1",
24
+ "@webiny/api-headless-cms": "6.4.2-beta.1",
25
+ "@webiny/app": "6.4.2-beta.1",
26
+ "@webiny/app-admin": "6.4.2-beta.1",
27
+ "@webiny/background-tasks": "6.4.2-beta.1",
28
+ "@webiny/feature": "6.4.2-beta.1",
29
+ "@webiny/handler-graphql": "6.4.2-beta.1",
30
+ "@webiny/icons": "6.4.2-beta.1",
31
+ "@webiny/sdk": "6.4.2-beta.1",
32
+ "@webiny/utils": "6.4.2-beta.1",
33
33
  "lodash": "4.18.1",
34
34
  "mobx": "6.15.3",
35
35
  "mobx-react-lite": "4.1.1",
@@ -39,13 +39,13 @@
39
39
  "zod": "4.4.3"
40
40
  },
41
41
  "devDependencies": {
42
- "@webiny/api": "6.4.1",
43
- "@webiny/build-tools": "6.4.1",
42
+ "@webiny/api": "6.4.2-beta.1",
43
+ "@webiny/build-tools": "6.4.2-beta.1",
44
44
  "@webiny/di": "1.0.1",
45
- "@webiny/handler": "6.4.1",
46
- "@webiny/handler-aws": "6.4.1",
47
- "@webiny/plugins": "6.4.1",
48
- "@webiny/project-utils": "6.4.1",
45
+ "@webiny/handler": "6.4.2-beta.1",
46
+ "@webiny/handler-aws": "6.4.2-beta.1",
47
+ "@webiny/plugins": "6.4.2-beta.1",
48
+ "@webiny/project-utils": "6.4.2-beta.1",
49
49
  "typescript": "6.0.3",
50
50
  "vitest": "4.1.7"
51
51
  },