@go-labs-sg/rsvp 1.3.0 → 1.5.0
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.
- package/README.md +152 -7
- package/dist/index.js +131 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ rsvp event seating draft preview --organization-id org_123 --event-id evt_123 \
|
|
|
108
108
|
--expected-version 1 --ack-sensitive-data
|
|
109
109
|
rsvp event seating draft publish --organization-id org_123 --event-id evt_123 \
|
|
110
110
|
--expected-version 1 --request-id 123e4567-e89b-42d3-a456-426614174000 \
|
|
111
|
-
--reason 'Seat the confirmed guest' --allow-state-change --target evt_123
|
|
111
|
+
--reason 'Seat the confirmed guest' --allow-state-change --allow-email --target evt_123
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
Save and Publish require the latest `expectedVersion`. A successful Publish applies
|
|
@@ -116,12 +116,37 @@ all changed guests atomically and clears only that version of your draft. Resolv
|
|
|
116
116
|
preview issues before publishing; conflicts leave all bookings and the draft intact.
|
|
117
117
|
For an unknown outcome, retry the same UUID `requestId`, version, reason and email
|
|
118
118
|
choice: the durable receipt returns the previous counts without sending again or
|
|
119
|
-
clearing a newer draft. A different intent needs a new request ID.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
clearing a newer draft. A different intent needs a new request ID. Preserve the
|
|
120
|
+
exact `seatChangeEmailRegistrationIds` set on retry (order is immaterial); changing
|
|
121
|
+
it, including changing between omitted and `[]`, rejects reuse of the request ID.
|
|
122
|
+
|
|
123
|
+
Preview returns `noticeRecipients`: one row per affected registration, with a
|
|
124
|
+
registration ID, a grant-scoped name, `eligible`, and an `ineligibleReason` when
|
|
125
|
+
unavailable. No email addresses are exposed by this seating response. Review both
|
|
126
|
+
eligible and ineligible rows before choosing who receives mail; several moving
|
|
127
|
+
party members still produce only one recipient registration.
|
|
128
|
+
|
|
129
|
+
Use `seatChangeEmailRegistrationIds` in a full `--payload` to choose the exact
|
|
130
|
+
eligible affected registrations. Leave a registration out to publish its seat
|
|
131
|
+
changes without email. `[]` explicitly sends no email, **including when the event
|
|
132
|
+
has automatic seat-change notifications**. Selecting an unaffected registration,
|
|
133
|
+
an ineligible recipient or duplicate IDs is rejected before publishing. The API
|
|
134
|
+
rechecks permissions and eligibility under the publish transaction, not just in
|
|
135
|
+
preview. Sending requires notice permission. An explicit empty array does not.
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
rsvp event seating draft publish --allow-state-change --allow-email --target evt_123 \
|
|
139
|
+
--payload '{"organizationId":"org_123","eventId":"evt_123","expectedVersion":1,"requestId":"123e4567-e89b-42d3-a456-426614174000","reason":"Seat the confirmed party","sendSeatChangeEmail":true,"seatChangeEmailRegistrationIds":["reg_123"]}'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Do not combine `--payload` with command-local version/reason/request flags. If the
|
|
143
|
+
recipient field is omitted, existing behavior remains: `sendSeatChangeEmail: true`
|
|
144
|
+
requests all affected registrations, otherwise the automatic event policy still
|
|
145
|
+
applies. Every draft publish conservatively requires CLI `--allow-email` (or the
|
|
146
|
+
interactive effects confirmation), even for explicit `[]`; it approves an effect
|
|
147
|
+
but does not enable sending. Use the matching server/client revision for explicit
|
|
148
|
+
recipient choices; older servers reject the new field rather than silently
|
|
149
|
+
ignoring it. Preview counts recipient registrations, not guests. On realtime-enabled servers,
|
|
125
150
|
free new targets require validated per-registration holds at Publish, supplied as
|
|
126
151
|
`seatHolds: [{registrationId, holds: [{seatMapId, clientId, holdToken}]}]` in the
|
|
127
152
|
payload. Acquire these through the existing organizer hold-token flow; Stage never
|
|
@@ -237,6 +262,14 @@ Replace illustrative IDs and revisions with current readback values. Deploy API
|
|
|
237
262
|
policy enforcement before clients; an old API does not understand this field.
|
|
238
263
|
No authentication, consent flags, command names, or credential protocol changes.
|
|
239
264
|
|
|
265
|
+
### Registration-flow choice labels
|
|
266
|
+
|
|
267
|
+
`SINGLE_SELECT`, `VISUAL_SINGLE_SELECT` and `MULTI_SELECT` choices accept a
|
|
268
|
+
trimmed `label` of 1–500 characters, so a required single-choice `MULTI_SELECT`
|
|
269
|
+
can show a full-sentence declaration beside its tick box. Choice `value` stays a
|
|
270
|
+
stable machine value of 1–160 characters. Older APIs reject labels over 160
|
|
271
|
+
characters; deploy the API before saving longer labels.
|
|
272
|
+
|
|
240
273
|
### Registration-flow date-limit messages
|
|
241
274
|
|
|
242
275
|
`DATE` and `DATETIME` custom fields accept optional
|
|
@@ -537,6 +570,56 @@ it for the active registration/edit definition. Deploy the updated server before
|
|
|
537
570
|
saving these settings because older validators discard unsupported fields.
|
|
538
571
|
No database schema migration or attendee backfill is required.
|
|
539
572
|
|
|
573
|
+
## Confirmation email layout, name, QR codes and attachments
|
|
574
|
+
|
|
575
|
+
In the form builder's **Flow settings → Confirmation email layout**, or through
|
|
576
|
+
`definition.communications.participant.email` with `event flow draft save`,
|
|
577
|
+
customise the participant confirmation email for every outcome of the form:
|
|
578
|
+
|
|
579
|
+
```json
|
|
580
|
+
{
|
|
581
|
+
"communications": {
|
|
582
|
+
"participant": {
|
|
583
|
+
"email": {
|
|
584
|
+
"heading": "Hello {{name}}!",
|
|
585
|
+
"eventLine": null,
|
|
586
|
+
"confirmationButtonLabel": "View my Quest pass",
|
|
587
|
+
"supportFooter": "Questions? Email quest@example.com",
|
|
588
|
+
"showEventDetails": false,
|
|
589
|
+
"includeCheckInQrCodes": true,
|
|
590
|
+
"attachments": []
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
- `{{name}}` works in template `subject`, `body`, `bodyRichText` and every
|
|
598
|
+
text field above. It uses the primary attendee's name, then the invitee's
|
|
599
|
+
name, and falls back to `there`.
|
|
600
|
+
- `heading`, `eventLine`, `confirmationButtonLabel` and `supportFooter`: omit to
|
|
601
|
+
keep the built-in text, `null` to hide that part, or a string to replace it.
|
|
602
|
+
A custom or hidden `supportFooter` also replaces the resubmission footer.
|
|
603
|
+
- `showEventDetails` (default `true`) controls the When/Where lines.
|
|
604
|
+
- `includeCheckInQrCodes` (default `false`) embeds each attendee's check-in QR
|
|
605
|
+
image once the event's check-in QR codes are released; before release the
|
|
606
|
+
email keeps the release message.
|
|
607
|
+
- `attachments`: up to 5 PDF, PNG or JPEG files, 10 MB each and 15 MB total.
|
|
608
|
+
Create an upload with `event flow confirmation attachment upload create`
|
|
609
|
+
(`organizationId`, `eventId`, `filename`, `contentType`, `byteSize`), `PUT`
|
|
610
|
+
the file unchanged to the returned `uploadUrl` with its `Content-Type`, then
|
|
611
|
+
add the returned `attachment` object to the list. Preview/publish reject keys
|
|
612
|
+
not uploaded for the same event, and publish verifies each uploaded object's
|
|
613
|
+
type and size.
|
|
614
|
+
|
|
615
|
+
Merge these fields into the complete current definition and publish as for
|
|
616
|
+
other form settings. Omitting `email` keeps existing emails unchanged. Deploy
|
|
617
|
+
the updated server before saving these settings. No database migration is
|
|
618
|
+
required.
|
|
619
|
+
|
|
620
|
+
`event flow preview` sends the definition as a POST body so large formatted
|
|
621
|
+
emails no longer exceed URL limits; it requires a server with this change.
|
|
622
|
+
|
|
540
623
|
## Administrator registration for an invitee
|
|
541
624
|
|
|
542
625
|
Organizers can register someone on their behalf at any time, including after
|
|
@@ -836,6 +919,49 @@ rsvp people registration update \
|
|
|
836
919
|
--payload '{"organizationId":"org_123","eventId":"evt_123","registrationId":"reg_123","expectedVersion":4,"reason":"Moved to finance table","seats":[{"registrationAttendeeId":"att_1","seatId":"seat_9"},{"registrationAttendeeId":"att_2","seatId":"seat_2"}],"seatChangeNotice":{"idempotencyKey":"4d68a320-013d-43c7-bfcc-d1126827d8c5"}}'
|
|
837
920
|
```
|
|
838
921
|
|
|
922
|
+
### Archive or cancel registrations
|
|
923
|
+
|
|
924
|
+
`people registration archive` and `people registration cancel` forward the same
|
|
925
|
+
permissioned, audited `event.bulkManageRegistrations` operation as the web app.
|
|
926
|
+
Both require server-side `rsvp.manage` permission and `--allow-state-change`;
|
|
927
|
+
`--target` must match the payload's **event ID**, not a registration ID.
|
|
928
|
+
|
|
929
|
+
Supply `organizationId`, `eventId`, an audit `reason` (3–500 characters after
|
|
930
|
+
trimming), and 1–100 unique `registrations`, each with `id` and its current
|
|
931
|
+
positive-integer `expectedVersion`. Get revisions from `people registration list`
|
|
932
|
+
or `people registration edit get`. The command sets `action` to `ARCHIVE` or
|
|
933
|
+
`CANCEL` when omitted; explicitly supplying any other action is rejected. Missing
|
|
934
|
+
or invalid fields, duplicate IDs and oversized batches fail before dispatch.
|
|
935
|
+
Stale revisions are checked by the server; refresh and review before retrying.
|
|
936
|
+
|
|
937
|
+
```sh
|
|
938
|
+
rsvp people registration archive \
|
|
939
|
+
--allow-state-change --target evt_123 \
|
|
940
|
+
--payload '{"organizationId":"org_123","eventId":"evt_123","reason":"Remove refunded test registrations","registrations":[{"id":"reg_123","expectedVersion":6},{"id":"reg_456","expectedVersion":2}]}'
|
|
941
|
+
|
|
942
|
+
rsvp people registration cancel \
|
|
943
|
+
--allow-state-change --target evt_123 \
|
|
944
|
+
--payload '{"organizationId":"org_123","eventId":"evt_123","reason":"Participant withdrew","registrations":[{"id":"reg_789","expectedVersion":3}]}'
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
- **Archive** sets `archivedAt` and removes the registrations from default lists
|
|
948
|
+
and exports. It also cancels active registrations through the normal release
|
|
949
|
+
path; this is not merely hiding an attending registration.
|
|
950
|
+
- **Cancel** cancels active registrations without changing `archivedAt`. Cancelled
|
|
951
|
+
registrations remain visible unless already archived.
|
|
952
|
+
- Both release consumed event capacity, active seat bookings and holds, cancel
|
|
953
|
+
session selections and waiting/offered waitlist entries, and run the existing
|
|
954
|
+
event/session waitlist maintenance. Released places may generate waitlist
|
|
955
|
+
offers and **emails to other participants**; neither command sends a
|
|
956
|
+
cancellation email to the affected registrants. No `--allow-email` flag is
|
|
957
|
+
required by these commands' existing `state-change` contract.
|
|
958
|
+
- Neither command automatically refunds a payment or deletes records. Payment,
|
|
959
|
+
refund and audit history are retained. Pending checkouts linked to a provider,
|
|
960
|
+
processing payments and payments requiring review must be reconciled first;
|
|
961
|
+
unlinked pending payment attempts are cancelled by the existing server logic.
|
|
962
|
+
- Use **Unarchive** below for archive visibility/fresh-response recovery, or
|
|
963
|
+
**Restore** for attending recovery. Unarchive does not undo cancellation.
|
|
964
|
+
|
|
839
965
|
### Unarchive for a fresh response versus attending Restore
|
|
840
966
|
|
|
841
967
|
`people registration unarchive` forwards the permissioned, audited
|
|
@@ -936,6 +1062,25 @@ previous effects.
|
|
|
936
1062
|
|
|
937
1063
|
Optional `registrationEmail` and `registrationMasterList` presentation settings
|
|
938
1064
|
are also written through `REGISTRATION_RULES`; omitted settings are preserved.
|
|
1065
|
+
|
|
1066
|
+
### Registration email sender
|
|
1067
|
+
|
|
1068
|
+
Confirmation and seat-change emails send from the server default
|
|
1069
|
+
(`RSVP_EMAIL_FROM`) unless the event sets a sender in `registrationEmail`:
|
|
1070
|
+
|
|
1071
|
+
- `senderName` changes only the display name.
|
|
1072
|
+
- `senderLocalPart` and `senderDomain` (set both or neither) change the address,
|
|
1073
|
+
for example `"senderLocalPart": "nelbd", "senderDomain": "getout.sg"` sends
|
|
1074
|
+
from `"NELBD Quest" <nelbd@getout.sg>`. `senderDomain` must be a Resend domain
|
|
1075
|
+
that is verified with sending enabled when the update is saved; list them with
|
|
1076
|
+
`rsvp event email sender-domains`. Invalid local parts, a missing half of the
|
|
1077
|
+
pair or an unverified domain are rejected.
|
|
1078
|
+
|
|
1079
|
+
`registrationEmail` replaces the whole presentation object, so read the current
|
|
1080
|
+
event first and resend every key you want to keep. Reply-to and support email
|
|
1081
|
+
are unchanged. If a saved domain is later unverified in Resend, those emails
|
|
1082
|
+
fail and are recorded as failed deliveries; they never fall back silently to a
|
|
1083
|
+
different sender. Fix the domain or remove the address fields to resume.
|
|
939
1084
|
See `examples/amgen-rsvp-copy/registration-presentation-patch.json` and its README
|
|
940
1085
|
for a reviewed activation fragment, output-key semantics, receipt/header behavior
|
|
941
1086
|
and the separate deployment/configuration/live-send approval gates. No event
|
package/dist/index.js
CHANGED
|
@@ -7195,7 +7195,8 @@ var logoutCliSession = async ({
|
|
|
7195
7195
|
// src/api-client.ts
|
|
7196
7196
|
import {
|
|
7197
7197
|
createTRPCProxyClient,
|
|
7198
|
-
httpBatchLink
|
|
7198
|
+
httpBatchLink,
|
|
7199
|
+
splitLink
|
|
7199
7200
|
} from "@trpc/client";
|
|
7200
7201
|
import SuperJSON from "superjson";
|
|
7201
7202
|
|
|
@@ -7213,18 +7214,28 @@ var normalizeApiBaseUrl = (value) => {
|
|
|
7213
7214
|
var getApiBaseUrl = (override) => normalizeApiBaseUrl(override ?? process.env.RSVP_API_URL ?? DEFAULT_RSVP_API_BASE_URL);
|
|
7214
7215
|
|
|
7215
7216
|
// src/api-client.ts
|
|
7216
|
-
var
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
}
|
|
7217
|
+
var POST_QUERY_PATHS = new Set([
|
|
7218
|
+
"eventFlow.preview"
|
|
7219
|
+
]);
|
|
7220
|
+
var createRsvpClient = (apiBaseUrl = getApiBaseUrl(), accessToken) => {
|
|
7221
|
+
const linkOptions = {
|
|
7222
|
+
headers: () => accessToken ? {
|
|
7223
|
+
authorization: `Bearer ${accessToken}`,
|
|
7224
|
+
"x-trpc-source": "rsvp-cli"
|
|
7225
|
+
} : { "x-trpc-source": "rsvp-cli" },
|
|
7226
|
+
transformer: SuperJSON,
|
|
7227
|
+
url: `${apiBaseUrl}/api/trpc`
|
|
7228
|
+
};
|
|
7229
|
+
return createTRPCProxyClient({
|
|
7230
|
+
links: [
|
|
7231
|
+
splitLink({
|
|
7232
|
+
condition: (op) => POST_QUERY_PATHS.has(op.path),
|
|
7233
|
+
true: httpBatchLink({ ...linkOptions, methodOverride: "POST" }),
|
|
7234
|
+
false: httpBatchLink(linkOptions)
|
|
7235
|
+
})
|
|
7236
|
+
]
|
|
7237
|
+
});
|
|
7238
|
+
};
|
|
7228
7239
|
|
|
7229
7240
|
// ../validators/src/assign-guests.ts
|
|
7230
7241
|
var assignGuestFiltersInputSchema = object({
|
|
@@ -7715,11 +7726,13 @@ var flowBlockBaseShape = {
|
|
|
7715
7726
|
title: string2().trim().min(1).max(240).optional(),
|
|
7716
7727
|
visibleWhen: eventFlowConditionGroupSchema.optional()
|
|
7717
7728
|
};
|
|
7729
|
+
var maxEventFlowChoiceLabelLength = 500;
|
|
7730
|
+
var maxEventFlowChoiceValueLength = 160;
|
|
7718
7731
|
var customFieldChoiceSchema = object({
|
|
7719
7732
|
assetId: eventFlowEntityIdSchema.optional(),
|
|
7720
7733
|
description: string2().trim().max(500).optional(),
|
|
7721
|
-
label: string2().trim().min(1).max(
|
|
7722
|
-
value: string2().trim().min(1).max(
|
|
7734
|
+
label: string2().trim().min(1).max(maxEventFlowChoiceLabelLength),
|
|
7735
|
+
value: string2().trim().min(1).max(maxEventFlowChoiceValueLength)
|
|
7723
7736
|
});
|
|
7724
7737
|
var maxEventFlowDateBoundMessageLength = 500;
|
|
7725
7738
|
var eventFlowDateBoundMessageSchema = string2().trim().min(1).max(maxEventFlowDateBoundMessageLength);
|
|
@@ -8030,7 +8043,53 @@ var confirmationBodyRichTextSchema = unknown().superRefine((value, ctx) => {
|
|
|
8030
8043
|
message: "Confirmation body must contain 1\u201310,000 characters"
|
|
8031
8044
|
});
|
|
8032
8045
|
});
|
|
8046
|
+
var eventFlowConfirmationAttachmentContentTypes = [
|
|
8047
|
+
"application/pdf",
|
|
8048
|
+
"image/jpeg",
|
|
8049
|
+
"image/png"
|
|
8050
|
+
];
|
|
8051
|
+
var maxEventFlowConfirmationAttachmentCount = 5;
|
|
8052
|
+
var maxEventFlowConfirmationAttachmentSize = 10 * 1024 * 1024;
|
|
8053
|
+
var maxEventFlowConfirmationAttachmentTotalSize = 15 * 1024 * 1024;
|
|
8054
|
+
var eventFlowConfirmationAttachmentFilenameSchema = string2().trim().min(1).max(120).regex(/^[^\\/:*?"<>|\r\n\t]+$/, "Attachment file names cannot contain path or control characters");
|
|
8055
|
+
var eventFlowConfirmationAttachmentSchema = strictObject({
|
|
8056
|
+
byteSize: number2().int().positive().max(maxEventFlowConfirmationAttachmentSize),
|
|
8057
|
+
contentType: _enum(eventFlowConfirmationAttachmentContentTypes),
|
|
8058
|
+
filename: eventFlowConfirmationAttachmentFilenameSchema,
|
|
8059
|
+
key: string2().trim().min(1).max(300)
|
|
8060
|
+
});
|
|
8061
|
+
var editableEmailCopySchema = (maxLength) => string2().trim().min(1).max(maxLength).nullable().optional();
|
|
8062
|
+
var eventFlowParticipantConfirmationEmailSchema = strictObject({
|
|
8063
|
+
attachments: array(eventFlowConfirmationAttachmentSchema).max(maxEventFlowConfirmationAttachmentCount).default([]),
|
|
8064
|
+
confirmationButtonLabel: editableEmailCopySchema(60),
|
|
8065
|
+
eventLine: editableEmailCopySchema(500),
|
|
8066
|
+
heading: editableEmailCopySchema(120),
|
|
8067
|
+
includeCheckInQrCodes: boolean2().default(false),
|
|
8068
|
+
showEventDetails: boolean2().default(true),
|
|
8069
|
+
supportFooter: editableEmailCopySchema(1000)
|
|
8070
|
+
}).superRefine((email, ctx) => {
|
|
8071
|
+
const totalSize = email.attachments.reduce((total, attachment) => total + attachment.byteSize, 0);
|
|
8072
|
+
if (totalSize > maxEventFlowConfirmationAttachmentTotalSize) {
|
|
8073
|
+
ctx.addIssue({
|
|
8074
|
+
code: "custom",
|
|
8075
|
+
message: "Confirmation attachments must total 15 MB or less",
|
|
8076
|
+
path: ["attachments"]
|
|
8077
|
+
});
|
|
8078
|
+
}
|
|
8079
|
+
const keys = new Set;
|
|
8080
|
+
for (const [index, attachment] of email.attachments.entries()) {
|
|
8081
|
+
if (keys.has(attachment.key)) {
|
|
8082
|
+
ctx.addIssue({
|
|
8083
|
+
code: "custom",
|
|
8084
|
+
message: "Each confirmation attachment can be added only once",
|
|
8085
|
+
path: ["attachments", index, "key"]
|
|
8086
|
+
});
|
|
8087
|
+
}
|
|
8088
|
+
keys.add(attachment.key);
|
|
8089
|
+
}
|
|
8090
|
+
});
|
|
8033
8091
|
var participantConfirmationSchema = object({
|
|
8092
|
+
email: eventFlowParticipantConfirmationEmailSchema.optional(),
|
|
8034
8093
|
enabled: boolean2(),
|
|
8035
8094
|
includeResponseDetails: boolean2().default(false),
|
|
8036
8095
|
replyTo: email2().optional(),
|
|
@@ -10052,10 +10111,17 @@ var PUBLIC_EVENT_VALIDATED_FONT_FAMILIES = [
|
|
|
10052
10111
|
"Zilla Slab Highlight"
|
|
10053
10112
|
];
|
|
10054
10113
|
|
|
10114
|
+
// ../validators/src/email-sender.ts
|
|
10115
|
+
var emailSenderLocalPartSchema = string2().trim().max(64, "Sender address must be 64 characters or fewer").regex(/^(?!.*\.\.)[a-z\d](?:[a-z\d._+-]{0,62}[a-z\d])?$/i, "Enter a valid sender address before @");
|
|
10116
|
+
var emailSenderDomainSchema = string2().trim().toLowerCase().regex(/^(?:[a-z\d](?:[a-z\d-]{0,61}[a-z\d])?\.)+[a-z]{2,63}$/, "Select a valid sending domain");
|
|
10117
|
+
var EMAIL_SENDER_PAIR_MESSAGE = "Choose a sender address and domain together";
|
|
10118
|
+
|
|
10055
10119
|
// ../validators/src/registration-email-presentation.ts
|
|
10056
10120
|
var registrationEmailPresentationSchema = strictObject({
|
|
10057
10121
|
layout: _enum(["DEFAULT", "GROUPED"]).default("DEFAULT"),
|
|
10058
10122
|
senderName: string2().trim().min(1).max(120).regex(/^[^<>\r\n]+$/).optional(),
|
|
10123
|
+
senderLocalPart: emailSenderLocalPartSchema.optional(),
|
|
10124
|
+
senderDomain: emailSenderDomainSchema.optional(),
|
|
10059
10125
|
introText: string2().trim().min(1).max(1e4).optional(),
|
|
10060
10126
|
menuDetailOutputKeys: array(string2().trim().min(1).max(120)).max(100).default([]),
|
|
10061
10127
|
submittedConsentOutputKeys: array(string2().trim().min(1).max(120)).max(100).default([]),
|
|
@@ -10063,6 +10129,13 @@ var registrationEmailPresentationSchema = strictObject({
|
|
|
10063
10129
|
useResubmissionFooter: boolean2().default(false),
|
|
10064
10130
|
supportEmail: email2().optional(),
|
|
10065
10131
|
showLuckyDrawId: boolean2().optional()
|
|
10132
|
+
}).superRefine((value, ctx) => {
|
|
10133
|
+
if (Boolean(value.senderLocalPart) !== Boolean(value.senderDomain))
|
|
10134
|
+
ctx.addIssue({
|
|
10135
|
+
code: "custom",
|
|
10136
|
+
message: EMAIL_SENDER_PAIR_MESSAGE,
|
|
10137
|
+
path: [value.senderDomain ? "senderLocalPart" : "senderDomain"]
|
|
10138
|
+
});
|
|
10066
10139
|
});
|
|
10067
10140
|
|
|
10068
10141
|
// ../validators/src/registration-master-list-presentation.ts
|
|
@@ -10390,7 +10463,10 @@ var eventTablePaginationSchema = object({
|
|
|
10390
10463
|
var listEventInviteesInputSchema = organizationEventByIdInputSchema.extend({
|
|
10391
10464
|
...eventTablePaginationSchema.shape,
|
|
10392
10465
|
audienceTierId: string2().min(1).nullable().optional(),
|
|
10393
|
-
status: _enum(InviteeStatus).optional()
|
|
10466
|
+
status: _enum(InviteeStatus).optional(),
|
|
10467
|
+
statuses: array(_enum(InviteeStatus)).min(1).max(7).optional(),
|
|
10468
|
+
cursor: string2().min(1).max(64).optional(),
|
|
10469
|
+
direction: _enum(["NEXT", "PREVIOUS"]).default("NEXT")
|
|
10394
10470
|
});
|
|
10395
10471
|
var listEventRegistrationsInputSchema = organizationEventByIdInputSchema.extend({
|
|
10396
10472
|
archive: _enum(["ACTIVE", "ARCHIVED", "ALL"]).default("ACTIVE"),
|
|
@@ -10674,8 +10750,8 @@ var emailCampaignDraftFieldsSchema = object({
|
|
|
10674
10750
|
audienceMode: _enum(["SEGMENT", "SELECTED"]).optional(),
|
|
10675
10751
|
selectedInviteeIds: array(string2().min(1)).max(1e4).optional(),
|
|
10676
10752
|
fromName: string2().trim().max(120, "From name must be 120 characters or fewer").regex(/^[^\r\n<>]*$/, "From name contains unsupported characters").optional(),
|
|
10677
|
-
fromSubDomain:
|
|
10678
|
-
fromDomain:
|
|
10753
|
+
fromSubDomain: emailSenderLocalPartSchema.optional(),
|
|
10754
|
+
fromDomain: emailSenderDomainSchema.optional(),
|
|
10679
10755
|
html: string2().trim().min(1, "Email body is required").max(1e5, "Email body is too long"),
|
|
10680
10756
|
name: string2().trim().min(1, "Campaign name is required").max(160, "Campaign name must be 160 characters or fewer"),
|
|
10681
10757
|
previewText: string2().trim().max(240, "Preview text must be 240 characters or fewer").optional(),
|
|
@@ -10693,7 +10769,7 @@ var validateSelectedCampaignAudience = (input, ctx) => {
|
|
|
10693
10769
|
ctx.addIssue({
|
|
10694
10770
|
code: "custom",
|
|
10695
10771
|
path: [input.fromDomain ? "fromSubDomain" : "fromDomain"],
|
|
10696
|
-
message:
|
|
10772
|
+
message: EMAIL_SENDER_PAIR_MESSAGE
|
|
10697
10773
|
});
|
|
10698
10774
|
};
|
|
10699
10775
|
var createEmailCampaignInputSchema = organizationEventByIdInputSchema.extend(emailCampaignDraftFieldsSchema.shape).superRefine(validateSelectedCampaignAudience);
|
|
@@ -10865,6 +10941,11 @@ var createEventFlowImageAssetUploadInputSchema = organizationEventByIdInputSchem
|
|
|
10865
10941
|
byteSize: number2().int().positive().max(maxEventFlowImageAssetSize),
|
|
10866
10942
|
mimeType: eventFlowImageAssetMimeTypeSchema
|
|
10867
10943
|
});
|
|
10944
|
+
var createEventFlowConfirmationAttachmentUploadInputSchema = organizationEventByIdInputSchema.extend({
|
|
10945
|
+
byteSize: number2().int().positive().max(maxEventFlowConfirmationAttachmentSize),
|
|
10946
|
+
contentType: _enum(eventFlowConfirmationAttachmentContentTypes),
|
|
10947
|
+
filename: eventFlowConfirmationAttachmentFilenameSchema
|
|
10948
|
+
});
|
|
10868
10949
|
var finalizeEventFlowImageAssetInputSchema = organizationEventByIdInputSchema.extend({
|
|
10869
10950
|
assetId: eventFlowImageAssetIdSchema
|
|
10870
10951
|
});
|
|
@@ -10968,6 +11049,10 @@ var createEventFlowConsentVersionInputSchema = organizationEventByIdInputSchema.
|
|
|
10968
11049
|
var setEventFlowGroupPasscodeInputSchema = organizationEventFlowInputSchema.extend({
|
|
10969
11050
|
passcode: string2().trim().min(8).max(160)
|
|
10970
11051
|
});
|
|
11052
|
+
var getEventFlowSeatCategoryColorsInputSchema = eventBySlugInputSchema.extend({
|
|
11053
|
+
flowVersionId: flowVersionIdSchema,
|
|
11054
|
+
seatMapId: flowVersionIdSchema
|
|
11055
|
+
}).strict();
|
|
10971
11056
|
var issueEventFlowSeatHoldTokenInputSchema = eventBySlugInputSchema.extend({
|
|
10972
11057
|
clientId: uuid2(),
|
|
10973
11058
|
flowVersionId: flowVersionIdSchema,
|
|
@@ -11961,6 +12046,9 @@ var publishSeatingDraftInputSchema = seatingDraftScopeSchema.extend({
|
|
|
11961
12046
|
requestId: uuid2(),
|
|
11962
12047
|
reason: string2().trim().min(1).max(500),
|
|
11963
12048
|
sendSeatChangeEmail: boolean2().default(false),
|
|
12049
|
+
seatChangeEmailRegistrationIds: array(string2().min(1)).max(100).refine((ids) => new Set(ids).size === ids.length, {
|
|
12050
|
+
message: "Each recipient registration may appear only once."
|
|
12051
|
+
}).optional(),
|
|
11964
12052
|
seatHolds: array(object({
|
|
11965
12053
|
registrationId: string2().min(1),
|
|
11966
12054
|
holds: array(object({
|
|
@@ -12048,7 +12136,7 @@ var commands = {
|
|
|
12048
12136
|
effects: [],
|
|
12049
12137
|
operation: (api, input) => api.eventFlow.preview.query(input),
|
|
12050
12138
|
payloadOnly: true,
|
|
12051
|
-
summary: "Validate and preview an event flow, including date-limit messages (--payload JSON)."
|
|
12139
|
+
summary: "Validate and preview an event flow, including date-limit messages; the definition is sent as a POST body (--payload JSON)."
|
|
12052
12140
|
},
|
|
12053
12141
|
"event flow draft get": {
|
|
12054
12142
|
effects: [],
|
|
@@ -12321,18 +12409,21 @@ var commands = {
|
|
|
12321
12409
|
summary: "Update a user's global role (--payload JSON)."
|
|
12322
12410
|
}
|
|
12323
12411
|
};
|
|
12324
|
-
var
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12412
|
+
var parseRegistrationManagementInput = (input, expectedAction) => {
|
|
12413
|
+
const inputSchema = bulkManageRegistrationsInputSchema.safeExtend({
|
|
12414
|
+
action: bulkManageRegistrationsInputSchema.shape.action.extract([
|
|
12415
|
+
expectedAction
|
|
12416
|
+
])
|
|
12417
|
+
});
|
|
12330
12418
|
const action = input ? Reflect.get(input, "action") : undefined;
|
|
12331
|
-
const parsed =
|
|
12419
|
+
const parsed = inputSchema.safeParse(input ? { ...input, action: action === undefined ? expectedAction : action } : input);
|
|
12332
12420
|
if (!parsed.success)
|
|
12333
12421
|
throw new CliUsageError(parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; "));
|
|
12334
12422
|
return parsed.data;
|
|
12335
12423
|
};
|
|
12424
|
+
var parseArchiveRegistrationsInput = (input) => parseRegistrationManagementInput(input, "ARCHIVE");
|
|
12425
|
+
var parseCancelRegistrationsInput = (input) => parseRegistrationManagementInput(input, "CANCEL");
|
|
12426
|
+
var parseUnarchiveRegistrationsInput = (input) => parseRegistrationManagementInput(input, "RESTORE");
|
|
12336
12427
|
var payloadCommand = (operation, summary, effects = [], targetKey) => ({
|
|
12337
12428
|
effects,
|
|
12338
12429
|
operation,
|
|
@@ -12403,6 +12494,7 @@ Object.assign(commands, {
|
|
|
12403
12494
|
"audit list": payloadCommand((api, input) => api.audit.listEventActivity.query(input), "List event audit activity (--payload JSON).", ["sensitive-data"]),
|
|
12404
12495
|
"event check-in qr": payloadCommand((api, input) => api.event.checkInByQr.mutate(input), "Check in using a QR token (--payload JSON).", ["state-change"]),
|
|
12405
12496
|
"event flow image upload create": payloadCommand((api, input) => api.eventFlow.createImageAssetUpload.mutate(input), "Create an event-local registration-flow image upload URL (--payload JSON).", ["external-write", "state-change"], "eventId"),
|
|
12497
|
+
"event flow confirmation attachment upload create": payloadCommand((api, input) => api.eventFlow.createConfirmationAttachmentUpload.mutate(input), "Create a confirmation-email attachment upload URL for a PDF, PNG or JPEG up to 10 MB (filename, contentType, byteSize); PUT the file there, then add the returned attachment to communications.participant.email.attachments (--payload JSON).", ["external-write", "state-change"], "eventId"),
|
|
12406
12498
|
"event flow image finalize": payloadCommand((api, input) => api.eventFlow.finalizeImageAsset.mutate(input), "Finalize an event-local registration-flow image after the external upload (--payload JSON).", ["state-change"], "assetId"),
|
|
12407
12499
|
"event logo upload create": payloadCommand((api, input) => api.event.createLogoUpload.mutate(input), "Create an event-logo upload URL (--payload JSON).", ["external-write", "state-change"], "eventId"),
|
|
12408
12500
|
"event logo update": payloadCommand((api, input) => api.event.updateLogo.mutate(input), "Set or clear the event logo (--payload JSON).", ["state-change"], "eventId"),
|
|
@@ -12418,6 +12510,7 @@ Object.assign(commands, {
|
|
|
12418
12510
|
"event seating table delete": payloadCommand((api, input) => api.event.deleteSeatTable.mutate(input), "Delete a seating table (--payload JSON).", ["delete", "state-change"]),
|
|
12419
12511
|
"event seating layout update": payloadCommand((api, input) => api.event.updateSeatTableLayout.mutate(input), "Update the seating layout and floor plan (--payload JSON).", ["state-change"], "eventId"),
|
|
12420
12512
|
"event seating table update": payloadCommand((api, input) => api.event.updateSeatTable.mutate(input), "Update a seating table (--payload JSON).", ["delete", "state-change"], "tableId"),
|
|
12513
|
+
"event email sender-domains": eventScopeQueryCommand((api, input) => api.event.getEmailSenderDomains.query(input), "List verified Resend sending domains for campaign and registration email sender addresses."),
|
|
12421
12514
|
"event audience-tier list": eventScopeQueryCommand((api, input) => api.event.listAudienceTiers.query(input), "List event audience tiers and assignment counts."),
|
|
12422
12515
|
"event audience-tier create": payloadCommand((api, input) => api.event.createAudienceTier.mutate(input), "Create an event audience tier (--payload JSON).", ["state-change"], "eventId"),
|
|
12423
12516
|
"event audience-tier update": payloadCommand((api, input) => api.event.updateAudienceTier.mutate(input), "Update an event audience tier (--payload JSON).", ["state-change"], "tierId"),
|
|
@@ -12450,6 +12543,14 @@ Object.assign(commands, {
|
|
|
12450
12543
|
{ effect: "email", whenPayloadField: "seatChangeNotice" }
|
|
12451
12544
|
]
|
|
12452
12545
|
},
|
|
12546
|
+
"people registration archive": {
|
|
12547
|
+
...payloadCommand((api, input) => api.event.bulkManageRegistrations.mutate(parseArchiveRegistrationsInput(input)), "Archive up to 100 unique registrations with expectedVersion and reason (3\u2013500 characters); action defaults to ARCHIVE and other actions are rejected. Requires rsvp.manage; target the eventId. Cancels active registrations, releases capacity, seats and holds, cancels session selections and waitlist entries/offers, and hides archived rows from default lists/exports. Unresolved checkouts must be reconciled first; no automatic refund. Not a delete: payment, refund and audit history remain. No cancellation email; released places may trigger waitlist-offer emails (--payload JSON).", ["state-change"], "eventId"),
|
|
12548
|
+
validateInput: parseArchiveRegistrationsInput
|
|
12549
|
+
},
|
|
12550
|
+
"people registration cancel": {
|
|
12551
|
+
...payloadCommand((api, input) => api.event.bulkManageRegistrations.mutate(parseCancelRegistrationsInput(input)), "Cancel up to 100 unique registrations with expectedVersion and reason (3\u2013500 characters); action defaults to CANCEL and other actions are rejected. Requires rsvp.manage; target the eventId. Cancels active registrations, releases capacity, seats and holds, and cancels session selections and waitlist entries/offers without changing archive visibility. Unresolved checkouts must be reconciled first; no automatic refund. Not a delete: payment, refund and audit history remain. No cancellation email; released places may trigger waitlist-offer emails (--payload JSON).", ["state-change"], "eventId"),
|
|
12552
|
+
validateInput: parseCancelRegistrationsInput
|
|
12553
|
+
},
|
|
12453
12554
|
"people registration unarchive": {
|
|
12454
12555
|
...payloadCommand((api, input) => api.event.bulkManageRegistrations.mutate(parseUnarchiveRegistrationsInput(input)), "Unarchive up to 100 unique registrations with expectedVersion and reason; action defaults to RESTORE and other actions are rejected. Target the eventId. Eligible cancelled nonattending invitees can submit afresh; historical registration, payment and QR are not reinstated. Fresh submissions use normal checks and new payment/credentials; attending recovery uses people registration restore (--payload JSON).", ["state-change"], "eventId"),
|
|
12455
12556
|
validateInput: parseUnarchiveRegistrationsInput
|
|
@@ -12463,7 +12564,7 @@ Object.assign(commands, {
|
|
|
12463
12564
|
"event mine list": payloadCommand((api, input) => api.event.listMyEvents.query(input), "List the caller's events (--payload JSON)."),
|
|
12464
12565
|
"event reminder list": payloadCommand((api, input) => api.event.listReminderSegments.query(input), "List reminder segments (--payload JSON).", ["sensitive-data"]),
|
|
12465
12566
|
"event rsvp submit": payloadCommand((api, input) => api.event.submitRsvp.mutate(input), "Submit the caller's registration (--payload JSON).", ["sensitive-data", "state-change"]),
|
|
12466
|
-
"event setup step update": payloadCommand((api, input) => api.event.updateSetupStep.mutate(input), "Update one revision-checked event setup step (--payload JSON). REGISTRATION_RULES accepts registrationEmail presentation, registrationMasterList output-key ordering/omissions and seatChangeNotification automatic policy; omitted settings are preserved.", ["state-change"]),
|
|
12567
|
+
"event setup step update": payloadCommand((api, input) => api.event.updateSetupStep.mutate(input), "Update one revision-checked event setup step (--payload JSON). REGISTRATION_RULES accepts registrationEmail presentation (including senderName and a senderLocalPart+senderDomain address on a verified Resend sending domain), registrationMasterList output-key ordering/omissions and seatChangeNotification automatic policy; omitted settings are preserved.", ["state-change"]),
|
|
12467
12568
|
"event page update": payloadCommand((api, input) => api.event.updateSetupStep.mutate({
|
|
12468
12569
|
...input,
|
|
12469
12570
|
section: "DETAILS_PAGE"
|
|
@@ -12541,7 +12642,7 @@ Object.assign(commands, {
|
|
|
12541
12642
|
"--expected-version": { key: "expectedVersion", type: "number" }
|
|
12542
12643
|
},
|
|
12543
12644
|
operation: (api, input) => api.event.getSeatingDraftPreview.query(getSeatingDraftPreviewInputSchema.parse(input)),
|
|
12544
|
-
summary: "Check
|
|
12645
|
+
summary: "Check fresh seats, grants and notification policy. Returns noticeRecipients: one eligible/ineligible row per affected registration with grant-scoped names, never email addresses; --expected-version is required."
|
|
12545
12646
|
},
|
|
12546
12647
|
"event seating draft publish": {
|
|
12547
12648
|
scope: "event",
|
|
@@ -12557,7 +12658,7 @@ Object.assign(commands, {
|
|
|
12557
12658
|
},
|
|
12558
12659
|
validateInput: (input) => validateSeatingDraftInput(publishSeatingDraftInputSchema, input),
|
|
12559
12660
|
operation: (api, input) => api.event.publishSeatingDraft.mutate(publishSeatingDraftInputSchema.parse(input)),
|
|
12560
|
-
summary: "Atomically publish
|
|
12661
|
+
summary: "Atomically publish with expectedVersion, UUID requestId and reason. Optional seatChangeEmailRegistrationIds in --payload chooses exact affected eligible registration recipients; [] sends none, including automatic policy. Omit to retain sendSeatChangeEmail/event-policy behavior. Requires --allow-email. Retry the same requestId and exact recipient set. Realtime free targets need per-registration seatHolds."
|
|
12561
12662
|
}
|
|
12562
12663
|
});
|
|
12563
12664
|
var getCommandManifest = () => ({
|