@go-labs-sg/rsvp 0.14.0 → 0.16.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.
Files changed (3) hide show
  1. package/README.md +155 -1
  2. package/dist/index.js +10 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  JSON-first command-line access to Registration organizations, events, guests, check-in, payments, reporting, retention, and administrative operations.
4
4
 
5
+ ## First step: update before use
6
+
7
+ Before starting a task, **update to the latest published release first**, including when an AI agent runs this CLI:
8
+
9
+ ```bash
10
+ bun add --global @go-labs-sg/rsvp@latest
11
+ rsvp version
12
+ rsvp --help
13
+ ```
14
+
15
+ Run this sequence once per task, not before every command. Re-read the updated help before choosing commands or flags. If updating fails, stop and report the failure rather than silently using an outdated CLI. If the user explicitly requested a pinned version or a development/staging build, preserve that version instead of replacing it with the public release.
16
+
17
+ New installation? Follow the runtime and installation instructions below to install Bun first, then return to this step.
18
+
5
19
  ## Runtime and installation
6
20
 
7
21
  The CLI requires [Bun](https://bun.com/docs/installation) 1.4.0 or newer. npm distributes the package, while the installed command runs under Bun.
@@ -77,7 +91,7 @@ Argument-parsing errors use a safe command label and never echo option values,
77
91
  including roster JSON passed through `--payload`. Surrounding shell history and
78
92
  automation can still record arguments independently of the CLI's error output.
79
93
 
80
- Use `rsvp help` for the command catalogue. Every response is a JSON envelope on stdout; errors and diagnostics go to stderr. `rsvp manifest` emits the machine-readable command reference for tooling.
94
+ Use `rsvp help` or `rsvp --help` for the command catalogue. `--help=true` and `--help=1` also show help; `--help=false` and `--help=0` preserve normal command execution. Other inline help values are rejected before command execution, even if a later `--help` flag is valid. Every response is a JSON envelope on stdout; errors and diagnostics go to stderr. `rsvp manifest` emits the machine-readable command reference for tooling.
81
95
 
82
96
  ## Public event page and images
83
97
 
@@ -121,6 +135,87 @@ rsvp event flow versions list --organization-id org_123 --event-id evt_123
121
135
  rsvp event flow resources get --organization-id org_123 --event-id evt_123
122
136
  ```
123
137
 
138
+ ### Registration-flow image upload lifecycle
139
+
140
+ Registration-flow images are **named, event-local assets**. Create one with an
141
+ optional `altText`, upload the bytes to the returned presigned URL, and then
142
+ finalize that same asset. Creation and finalization store the asset; neither
143
+ changes the draft or publishes a registration flow.
144
+
145
+ The API validator accepts `image/jpeg`, `image/png`, and `image/webp`. `byteSize`
146
+ must be a positive integer no larger than **10 MiB (10,485,760 bytes)**. The
147
+ server rechecks the uploaded object's content type and exact declared size when
148
+ finalizing. Use `event flow resources get` to verify the finalized asset ID in
149
+ that event's catalog; never reuse an actual event's asset ID in a test event.
150
+
151
+ ```sh
152
+ created="$(rsvp event flow image upload create \
153
+ --allow-external-write \
154
+ --allow-state-change \
155
+ --target evt_123 \
156
+ --payload '{"organizationId":"org_123","eventId":"evt_123","mimeType":"image/png","byteSize":2048,"altText":"Beef entrée"}')"
157
+
158
+ # Read data.asset.id and data.uploadUrl from the JSON response, then PUT the exact
159
+ # bytes to uploadUrl using the same MIME type and declared byteSize.
160
+ curl --fail --upload-file ./beef-entrée.png \
161
+ -H 'Content-Type: image/png' \
162
+ "<uploadUrl from the create response>"
163
+
164
+ rsvp event flow image finalize \
165
+ --allow-state-change \
166
+ --target '<asset.id from the create response>' \
167
+ --payload '{"organizationId":"org_123","eventId":"evt_123","assetId":"<asset.id from the create response>"}'
168
+ ```
169
+
170
+ The CLI does not perform the external `PUT`, retry uploads automatically, or
171
+ bypass authentication, event permissions, storage validation, or the existing
172
+ server contract. If the upload or finalization fails, inspect the error and
173
+ perform an explicit operator action; do not invent a new storage or retry
174
+ protocol. Reference the finalized asset from the appropriate form choice, then
175
+ save and publish the flow separately when the complete draft is approved.
176
+
177
+
178
+ ## Per-form confirmation presentation
179
+
180
+ In the form builder's **Flow settings → Confirmation and check-in pass**, set
181
+ lucky-draw visibility, primary/additional participant labels, and organiser
182
+ support-contact visibility. Save and publish the exact form to apply changes.
183
+ Draft edits do not affect live passes.
184
+
185
+ The same settings are supported in `definition.confirmation` through
186
+ `event flow draft save`:
187
+
188
+ ```json
189
+ {
190
+ "confirmation": {
191
+ "showLuckyDrawId": false,
192
+ "showSupportContact": false,
193
+ "primaryAttendeeLabel": "Participant 1",
194
+ "additionalAttendeeLabel": "Participant 2"
195
+ }
196
+ }
197
+ ```
198
+
199
+ Merge these fields into the complete current definition; this is not a complete
200
+ save payload. Include `organizationId`, `eventId`, the exact `flowId`, and the
201
+ latest `expectedRevision`, then publish with `expectedDraftRevision`. Use the
202
+ event ID as `--target` and pass `--allow-state-change` for both mutations.
203
+
204
+ Omitted visibility settings retain legacy behavior (shown). Omitted labels use
205
+ the stored attendee-type label; `null` hides a label. Custom labels must be
206
+ nonempty after trimming and at most 120 characters. Completion `contactEmail`
207
+ is optional; hiding support contact does not remove an email written into the
208
+ completion message or hide the participant's confirmation-recipient address.
209
+
210
+ Published display settings and completion message/contact updates apply to
211
+ existing registrations of the same form. Their saved questions, answer scope,
212
+ registration outcomes, attendee roles, lucky-draw records, QR credentials, and
213
+ check-in references remain unchanged. `event flow published get` accepts
214
+ `confirmation: true` in its payload for this saved-response presentation; omit
215
+ it for the active registration/edit definition. Deploy the updated server before
216
+ saving these settings because older validators discard unsupported fields.
217
+ No database schema migration or attendee backfill is required.
218
+
124
219
  ## Administrator registration for an invitee
125
220
 
126
221
  Inspect the invitee's active registration form and current registration version
@@ -207,6 +302,51 @@ rsvp check-in by-reference \
207
302
 
208
303
  High-impact payment and retention commands remain protected by their matching financial, deletion, external-write, and sensitive-data gates. The API always re-evaluates the authenticated user's current Registration role, organization membership, event assignment, and resource permissions.
209
304
 
305
+ ## Operational report exports
306
+
307
+ `export request` accepts `format: "XLSX"` (the default when omitted) or `"CSV"`.
308
+ Use `filters.view` to name the population rather than relying on a dataset label:
309
+
310
+ - RSVP: `MASTER` (all invitees, grouped employee/guest responses; default),
311
+ `CURRENT` (current response rows per person), `HISTORY` (all registration
312
+ records, not every edit revision), or `CLIENT_REGISTRATION` (current completed
313
+ employee/guest responses, including declines; excludes nonrespondents/drafts).
314
+ The client XLSX has **Attending**, **Not Attending**, **Master**, and **Metadata**
315
+ sheets; its CSV contains Master data only. Guest staff/department fields
316
+ describe the host, while menu and dietary answers remain person-scoped.
317
+ - SEATING: `CURRENT` (active bookings; default) or `HISTORY` (active and released).
318
+ - ATTENDANCE: `CURRENT` (expected people; default) or `CHECKED_IN` (expected people
319
+ with a check-in that has not been undone), or `ALL_INVITEES` (roster invitees,
320
+ including nonrespondents/declines, plus current guests). Registered, submitted,
321
+ attending, and active check-in states remain separate. None defines draw
322
+ eligibility.
323
+
324
+ Form, registration-status and submission-date filters apply only to RSVP.
325
+ Other datasets do not accept `view`. These combinations are validated by the API.
326
+
327
+ ```sh
328
+ rsvp export request \
329
+ --ack-sensitive-data \
330
+ --allow-state-change \
331
+ --target evt_123 \
332
+ --payload '{"organizationId":"org_123","eventId":"evt_123","dataset":"RSVP","format":"XLSX","filters":{"view":"MASTER"},"reason":"Organizer master list"}'
333
+ ```
334
+
335
+ Use `export list` to check the requester-scoped job, then `export download` for
336
+ its current authorized download URL. For the client workbook, replace `MASTER`
337
+ in the example with `CLIENT_REGISTRATION`. For the all-invitee attendance report,
338
+ set `dataset` to `ATTENDANCE` and `filters.view` to `ALL_INVITEES`.
339
+
340
+ Operational check-in accepts `ATTENDING` and legacy `SUBMITTED`; roster/detail,
341
+ manual/QR/reference entry, `report overview`, and `event people overview` use that same
342
+ population. Non-operational statuses remain excluded, and permissions, payment
343
+ gates, duplicate protection, and undo behavior are unchanged. The web panel's
344
+ realtime connection and manual refresh controls do not add a CLI subscription.
345
+
346
+ Deploy matching API and export-worker versions before requesting the new views;
347
+ old servers/workers do not understand them. Existing CLI commands pass the JSON
348
+ payload to the shared typed API, so no new command or client-only rules are needed.
349
+
210
350
  ## Seating updates
211
351
 
212
352
  `event seating layout update` moves tables, changes table geometry, and can save a floor plan. It requires `--allow-state-change`; its `--target` must match the payload's top-level `eventId`, not a nested table or seat-map ID:
@@ -295,6 +435,20 @@ rsvp template create \
295
435
 
296
436
  Instantiate the returned template version through `rsvp template instantiate`, then use the existing staged roster import. The example expects roster columns `email`, `name`, `staffId`, and `employmentType`; only `FTE` and `INTERN` values are configured as eligible profiles. Rules for other events should be expressed in their own template payloads using the same generic contracts.
297
437
 
438
+ ## Monorepo development
439
+
440
+ Follow the [development workflow](../../../docs/development-workflow.md#required-cli-coverage). App/API changes affecting this CLI must update its commands, types/input-output contracts, help/docs and verification in the same change. Use the existing authenticated product API rather than CLI-only business logic. Presentation-only changes do not require CLI edits; record why when no CLI update was needed.
441
+
442
+ From the repository root after isolated-worktree initialization:
443
+
444
+ ```bash
445
+ bun --filter @go-labs-sg/rsvp typecheck
446
+ bun --filter @go-labs-sg/rsvp build
447
+ bun run packages/rsvp/cli/src/index.ts help
448
+ ```
449
+
450
+ Building is not publication or permission to mutate live data. Use focused temporary business-behavior tests and the final pre-push gate from the shared workflow. Use this package's actual scripts; do not assume it has a command-artifact generator.
451
+
298
452
  ## Managed organization provisioning
299
453
 
300
454
  `organization create` requires an `ownerEmail` in its JSON payload and the
package/dist/index.js CHANGED
@@ -6549,7 +6549,7 @@ var commands = {
6549
6549
  effects: ["sensitive-data", "state-change"],
6550
6550
  operation: (api, input) => api.export.requestExport.mutate(input),
6551
6551
  payloadOnly: true,
6552
- summary: "Request an export (--payload JSON)."
6552
+ summary: "Request an operational report (--payload JSON; format CSV/XLSX, default XLSX; RSVP views MASTER/CURRENT/HISTORY/CLIENT_REGISTRATION; ATTENDANCE views CURRENT/CHECKED_IN/ALL_INVITEES; SEATING views CURRENT/HISTORY)."
6553
6553
  },
6554
6554
  "export list": {
6555
6555
  effects: ["sensitive-data"],
@@ -6626,6 +6626,8 @@ Object.assign(commands, {
6626
6626
  "admission identity-exception resolve": payloadCommand((api, input) => api.admission.resolveIdentityException.mutate(input), "Resolve an identity exception (--payload JSON).", ["sensitive-data", "state-change"]),
6627
6627
  "audit list": payloadCommand((api, input) => api.audit.listEventActivity.query(input), "List event audit activity (--payload JSON).", ["sensitive-data"]),
6628
6628
  "event check-in qr": payloadCommand((api, input) => api.event.checkInByQr.mutate(input), "Check in using a QR token (--payload JSON).", ["state-change"]),
6629
+ "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"),
6630
+ "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"),
6629
6631
  "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"),
6630
6632
  "event logo update": payloadCommand((api, input) => api.event.updateLogo.mutate(input), "Set or clear the event logo (--payload JSON).", ["state-change"], "eventId"),
6631
6633
  "event banner upload create": payloadCommand((api, input) => api.event.createBannerUpload.mutate(input), "Create a banner-image upload URL (--payload JSON).", ["external-write", "state-change"], "eventId"),
@@ -6692,6 +6694,7 @@ Object.assign(commands, {
6692
6694
  "waitlist offer respond": payloadCommand((api, input) => api.waitlist.respondToOffer.mutate(input), "Respond to a waitlist offer (--payload JSON).", ["state-change"])
6693
6695
  });
6694
6696
  var getCommandManifest = () => ({
6697
+ beforeUse: "First step before each task: update to the latest published release with 'bun add --global @go-labs-sg/rsvp@latest', then run 'rsvp version' and 'rsvp --help' before using commands. Update once per task. If updating fails, stop and report it. Preserve an explicitly requested pinned or development/staging version.",
6695
6698
  commands: [
6696
6699
  {
6697
6700
  effects: [],
@@ -6730,6 +6733,7 @@ var getCommandManifest = () => ({
6730
6733
  }))
6731
6734
  ],
6732
6735
  globalOptions: [
6736
+ "--help",
6733
6737
  "--api-url <url>",
6734
6738
  "--no-browser",
6735
6739
  "--organization-id <id>",
@@ -6792,6 +6796,7 @@ var booleanFlags = new Set([
6792
6796
  "--allow-external-write",
6793
6797
  "--allow-financial-write",
6794
6798
  "--allow-state-change",
6799
+ "--help",
6795
6800
  "--no-browser"
6796
6801
  ]);
6797
6802
  var valueFlags = new Set([
@@ -6819,6 +6824,9 @@ var parseArgs = (argv) => {
6819
6824
  throw new CliUsageError(`Unknown option: ${name}.`);
6820
6825
  const inlineValue = equalSignIndex === -1 ? undefined : argument.slice(equalSignIndex + 1);
6821
6826
  if (inlineValue !== undefined) {
6827
+ if (name === "--help" && !["true", "false", "1", "0"].includes(inlineValue)) {
6828
+ throw new CliUsageError("--help accepts only true, false, 1, or 0.");
6829
+ }
6822
6830
  flags.set(name, inlineValue);
6823
6831
  continue;
6824
6832
  }
@@ -6999,7 +7007,7 @@ var runRsvpCli = async (argv, dependencies) => {
6999
7007
  let command = "unknown";
7000
7008
  try {
7001
7009
  const parsed = parseArgs(argv);
7002
- const requestedCommand = parsed.positionals.join(" ") || "help";
7010
+ const requestedCommand = isEnabledFlag(parsed.flags, "--help") ? "help" : parsed.positionals.join(" ") || "help";
7003
7011
  if (!knownCommandNames.has(requestedCommand)) {
7004
7012
  throw new CliUsageError("Unknown command. Run 'rsvp help' to list commands.");
7005
7013
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/rsvp",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "RSVP CLI for authorized event operations.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",