@go-labs-sg/event-tech 1.0.0 → 1.2.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 +62 -0
  2. package/dist/index.js +478 -66
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -99,6 +99,68 @@ et lucky-draw participants list --event-id <id> --page 1 --per-page 100
99
99
 
100
100
  Commands emit deterministic JSON envelopes. Authentication credentials are never included in successful output, and bearer credentials are redacted from errors.
101
101
 
102
+ ### Event Passport
103
+
104
+ `et passport` uses the same typed procedures and event permissions as the web app.
105
+ Read `et --help` for all commands. Examples below use illustrative IDs and are not
106
+ an instruction to change a live event:
107
+
108
+ ```sh
109
+ et passport overview --event-id <id>
110
+ et passport login-options --event-id <id>
111
+ et passport mine --event-id <id>
112
+ et passport station upsert --event-id <id> --station-json '{"name":"Balance trail","collection":{"collectionMode":"STAFF_SCORE","maxPoints":20}}'
113
+ et passport station print-get --event-id <id> --station-id <id>
114
+ et passport station print-issue --event-id <id> --station-id <id> --expected-printed-qr-version <last-read-version>
115
+ et passport station print-revoke --event-id <id> --station-id <id> --expected-printed-qr-version <last-read-version> --allow-state-change --target <same-event-id>
116
+ et passport collect --event-id <id> --station-id <id> --profile-code <participant-code> --points 15
117
+ et passport claim --event-id <id> --code <station-code>
118
+ et passport participant detail --event-id <id> --participant-id <id>
119
+ et passport export --event-id <id>
120
+ ```
121
+
122
+ Station collection modes are `SELF_SCAN`, `STAFF_SCAN` and `STAFF_SCORE`.
123
+ `SELF_SCAN` uses a reusable printable QR; `STAFF_SCAN` is stamp-only; only
124
+ `STAFF_SCORE` accepts `collection.maxPoints` and a collection `--points` value.
125
+ Zero is valid. Repeat collection returns the original receipt without changing
126
+ points. Omit `collection` on an existing station edit to preserve its current
127
+ mode, including the legacy rotating-QR mode. Issuing/revoking printed codes uses
128
+ the last observed version to reject stale writes. Issue/rotation requires setup
129
+ permission; any event Operator can collect at any station.
130
+
131
+ `settings update --settings-json <json>` replaces the reward settings, so read
132
+ and copy the existing link, thresholds and redemption cap rather than clearing
133
+ them accidentally. Its JSON requires `linkedDrawEventId`,
134
+ `luckyDrawStampThreshold`, `prizeStampThreshold` and
135
+ `maxRedemptionsPerParticipant`; optional `loginMethods` is
136
+ `{"emailOtp":true,"google":false,"guest":true}`. Omit `loginMethods` to preserve
137
+ it. At least email OTP or Google must remain enabled for recovery, and enabling
138
+ Google requires configured provider credentials. Points never replace the
139
+ existing stamp-based reward thresholds.
140
+
141
+ `stamp correct`, `redemption reverse`, station/prize archive and print revocation
142
+ require `--allow-state-change --target <same-event-id>`; correction/reversal also
143
+ require a reason. Scored corrections accept `--points` and preserve historical
144
+ scores on revocation. Prize setup and redemption commands remain in `et --help`.
145
+ Participant reads/exports include points and nullable guest contact emails; do
146
+ not treat a null contact as an account lookup key.
147
+
148
+ Guest enrollment/account linking is browser-only: it requires the original guest
149
+ cookie and verified email/Google authentication. `mine` can read only the passport
150
+ owned by the current CLI identity; it cannot recover a guest by name or assume a
151
+ participant ID. No CLI auth transport or organiser access boundary is bypassed.
152
+ See the [Passport workflow and rollout gates](../../../docs/design/event-tech-passport-event-type.md).
153
+
154
+ ### Deprecated event types
155
+
156
+ Scavenger Hunt (Amazing Race) and Gardens by the Bay are deprecated and frozen.
157
+ Existing `event list`, `event get` and appearance commands retain their contracts
158
+ and can still return historical `SCAVENGER_HUNT` / `GARDENS_BY_THE_BAY` values.
159
+ The CLI has no event-create, duplicate, type-change or scavenger-specific commands;
160
+ no replacement commands or scavenger read-shape parity will be added. The server
161
+ blocks new creation, duplication and changes into these types, including requests
162
+ from older/custom clients. See the [retirement policy](../../../docs/agents/event-tech-deprecated-scavenger.md).
163
+
102
164
  ### Event appearance and Photo Wall display
103
165
 
104
166
  `event appearance get` returns the canonical appearance, its optimistic-lock
package/dist/index.js CHANGED
@@ -35,16 +35,16 @@ var __toESM = (mod, isNodeMode, target) => {
35
35
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
36
36
  var __require = import.meta.require;
37
37
 
38
- // ../../../node_modules/.bun/dotenv@18.0.7/node_modules/dotenv/dist/index.cjs
38
+ // ../../../node_modules/.bun/dotenv@18.0.8/node_modules/dotenv/dist/index.cjs
39
39
  var require_dist = __commonJS(function(exports, module) {
40
- var k = (e, n) => () => {
40
+ var j = (e, n) => () => {
41
41
  try {
42
42
  return n || e((n = { exports: {} }).exports, n), n.exports;
43
43
  } catch (t) {
44
44
  throw n = 0, t;
45
45
  }
46
46
  };
47
- var I = k((xe, U) => {
47
+ var k = j((xe, U) => {
48
48
  function G(e) {
49
49
  return typeof e == "string" ? !["false", "0", "no", "off", ""].includes(e.toLowerCase()) : !!e;
50
50
  }
@@ -58,8 +58,8 @@ var require_dist = __commonJS(function(exports, module) {
58
58
  }
59
59
  U.exports = { parseBoolean: G, optionsFromEnv: Y };
60
60
  });
61
- var N = k((ye, x) => {
62
- var z = __require("fs"), S = __require("path"), Z = __require("os"), { URL: ee, fileURLToPath: te } = __require("url"), { parseBoolean: $, optionsFromEnv: B } = I(), re = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg, b = new Uint8Array(256);
61
+ var N = j((ye, x) => {
62
+ var z = __require("fs"), I = __require("path"), Z = __require("os"), { URL: ee, fileURLToPath: te } = __require("url"), { parseBoolean: $, optionsFromEnv: B } = k(), re = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg, b = new Uint8Array(256);
63
63
  for (let e = 48;e <= 57; e++)
64
64
  b[e] = 1;
65
65
  for (let e = 65;e <= 90; e++)
@@ -124,7 +124,7 @@ var require_dist = __commonJS(function(exports, module) {
124
124
  r++;
125
125
  continue;
126
126
  }
127
- let p = t.slice(l, r), f = r;
127
+ let h = t.slice(l, r), f = r;
128
128
  if (r >= o && (d = 0), w(d))
129
129
  do
130
130
  r++, d = r < o ? t.charCodeAt(r) : 0;
@@ -141,8 +141,8 @@ var require_dist = __commonJS(function(exports, module) {
141
141
  let c = r, a = r;
142
142
  for (;a < o && w(t.charCodeAt(a)); )
143
143
  a++;
144
- let h = t.charCodeAt(a), g, y = false;
145
- if (h === 39 || h === 34 || h === 96) {
144
+ let g = t.charCodeAt(a), p, y = false;
145
+ if (g === 39 || g === 34 || g === 96) {
146
146
  let v = t[a], u = t.indexOf(v, a + 1), m = -1, C = -1;
147
147
  for (;u !== -1; ) {
148
148
  let O = t.charCodeAt(u - 1) === 92, E = u + 1;
@@ -153,7 +153,7 @@ var require_dist = __commonJS(function(exports, module) {
153
153
  u = t.indexOf(v, u + 1);
154
154
  }
155
155
  if (m !== -1) {
156
- if (g = t.slice(a + 1, m), r = C, t.charCodeAt(r) === 35)
156
+ if (p = t.slice(a + 1, m), r = C, t.charCodeAt(r) === 35)
157
157
  for (;r < o && !q(t.charCodeAt(r)); )
158
158
  r++;
159
159
  y = true;
@@ -175,12 +175,12 @@ var require_dist = __commonJS(function(exports, module) {
175
175
  for (;C > m && w(t.charCodeAt(C - 1)); )
176
176
  C--;
177
177
  let O = t.charCodeAt(m);
178
- if (C - m >= 2 && (O === 39 || O === 34 || O === 96) && t.charCodeAt(C - 1) === O ? g = t.slice(m + 1, C - 1) : g = t.slice(m, C), r = u, u < v)
178
+ if (p = t.slice(m, C), p.includes("\u2028") || p.includes("\u2029") ? p = p.replace(/^(['"`])([\s\S]*)\1$/mg, "$2") : C - m >= 2 && (O === 39 || O === 34 || O === 96) && t.charCodeAt(C - 1) === O && (p = t.slice(m + 1, C - 1)), r = u, u < v)
179
179
  for (;r < o && !q(t.charCodeAt(r)); )
180
180
  r++;
181
181
  }
182
- h === 34 && (y || a < r) && g.indexOf("\\") !== -1 && (g = g.replace(/\\n/g, `
183
- `).replace(/\\r/g, "\r")), n[p] = g;
182
+ g === 34 && (y || a < r) && p.indexOf("\\") !== -1 && (p = p.replace(/\\n/g, `
183
+ `).replace(/\\r/g, "\r")), n[h] = p;
184
184
  }
185
185
  return n;
186
186
  }
@@ -194,7 +194,7 @@ var require_dist = __commonJS(function(exports, module) {
194
194
  console.error(`\u25C7 ${e}`);
195
195
  }
196
196
  function V(e) {
197
- return e[0] === "~" ? S.join(Z.homedir(), e.slice(1)) : e;
197
+ return e[0] === "~" ? I.join(Z.homedir(), e.slice(1)) : e;
198
198
  }
199
199
  function ce(e = {}) {
200
200
  let n = { ...e };
@@ -204,7 +204,7 @@ var require_dist = __commonJS(function(exports, module) {
204
204
  }
205
205
  function ae(e) {
206
206
  e = ce(e);
207
- let n = S.resolve(process.cwd(), ".env"), t = "utf8", o = process.env;
207
+ let n = I.resolve(process.cwd(), ".env"), t = "utf8", o = process.env;
208
208
  e && e.processEnv != null && (o = e.processEnv);
209
209
  let r = $(e && e.debug);
210
210
  e && e.encoding ? t = e.encoding : r && T("no encoding is specified (UTF-8 is used by default)");
@@ -225,15 +225,15 @@ var require_dist = __commonJS(function(exports, module) {
225
225
  } catch (a) {
226
226
  r && T(`failed to load ${c} ${a.message}`), i = a;
227
227
  }
228
- let p = A.populate(o, l, e), f = $(Object.prototype.hasOwnProperty.call(e, "quiet") ? e.quiet : B(o).quiet);
228
+ let h = A.populate(o, l, e), f = $(Object.prototype.hasOwnProperty.call(e, "quiet") ? e.quiet : B(o).quiet);
229
229
  if (r || !f) {
230
- let c = Object.keys(p).length, a = [];
231
- for (let h of s)
230
+ let c = Object.keys(h).length, a = [];
231
+ for (let g of s)
232
232
  try {
233
- let g = S.relative(process.cwd(), h instanceof ee ? te(h) : h);
234
- a.push(g);
235
- } catch (g) {
236
- r && T(`failed to load ${h} ${g.message}`), i = g;
233
+ let p = I.relative(process.cwd(), g instanceof ee ? te(g) : g);
234
+ a.push(p);
235
+ } catch (p) {
236
+ r && T(`failed to load ${g} ${p.message}`), i = p;
237
237
  }
238
238
  ie(`injected env (${c}) from ${a.join(",")}`);
239
239
  }
@@ -259,7 +259,7 @@ var require_dist = __commonJS(function(exports, module) {
259
259
  x.exports.populate = A.populate;
260
260
  x.exports = A;
261
261
  });
262
- var M = k((Te, W) => {
262
+ var M = j((Te, W) => {
263
263
  var _ = __require("child_process"), ue = __require("fs"), L = __require("path");
264
264
  function de(e) {
265
265
  let n = ['"'], t = 0;
@@ -291,10 +291,10 @@ var require_dist = __commonJS(function(exports, module) {
291
291
  let o = (P(n, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean), s = o.some((l) => e.toLowerCase().endsWith(l.toLowerCase())) ? ["", ...o] : [...o, ""], i = /[\\/]/.test(e) ? [t] : [t, ...(P(n, "PATH") || "").split(";")];
292
292
  for (let l of i)
293
293
  for (let d of s) {
294
- let p = L.resolve(t, l.replace(/^"|"$/g, ""), e + d);
294
+ let h = L.resolve(t, l.replace(/^"|"$/g, ""), e + d);
295
295
  try {
296
- if (ue.statSync(p).isFile())
297
- return p;
296
+ if (ue.statSync(h).isFile())
297
+ return h;
298
298
  } catch {}
299
299
  }
300
300
  }
@@ -312,18 +312,18 @@ var require_dist = __commonJS(function(exports, module) {
312
312
  }
313
313
  W.exports = he;
314
314
  });
315
- var X = k(($e, F) => {
316
- var ge = __require("fs"), me = __require("os"), Q = __require("path"), ve = __require("child_process"), Ce = M(), R = N(), { optionsFromEnv: J } = I();
315
+ var X = j(($e, F) => {
316
+ var ge = __require("fs"), me = __require("os"), Q = __require("path"), ve = __require("child_process"), Ce = M(), R = N(), { optionsFromEnv: J } = k();
317
317
  function D() {
318
318
  console.log(["Usage: dotenv run [--help] [-q|--quiet] [--debug] [--override] [--fast] [-f|--file <paths>] [--] <command> [args...]", "", "Run a command with environment variables from a .env file.", "Place dotenv options before the command; all following arguments go to the command.", "", "Options:", " -f, --file <paths> .env paths, comma-separated or repeated (default: .env)", " -q, --quiet suppress the injected env message", " --debug enable debug logging", " --override override existing environment variables", " --fast use the faster character-scanner parser", "", "Environment variables (DOTENV_CONFIG_* names remain as fallbacks):", " DOTENV_PATH, DOTENV_ENCODING, DOTENV_QUIET,", " DOTENV_DEBUG, DOTENV_OVERRIDE,", " DOTENV_FAST"].join(`
319
319
  `));
320
320
  }
321
321
  function we(e) {
322
322
  let n = [], t = false, o, r, s, i, l = -1;
323
- for (let p = 0;p < e.length; p++) {
324
- let f = e[p];
323
+ for (let h = 0;h < e.length; h++) {
324
+ let f = e[h];
325
325
  if (f === "--") {
326
- l = p + 1;
326
+ l = h + 1;
327
327
  break;
328
328
  }
329
329
  if (f === "--help" || f === "-h")
@@ -345,18 +345,18 @@ var require_dist = __commonJS(function(exports, module) {
345
345
  continue;
346
346
  }
347
347
  if (f === "-f" || f === "--file" || f.startsWith("-f=") || f.startsWith("--file=")) {
348
- let c = f.indexOf("="), a = c === -1 ? f : f.slice(0, c), h = c === -1 ? e[++p] : f.slice(c + 1);
349
- if (!h || h === "--")
348
+ let c = f.indexOf("="), a = c === -1 ? f : f.slice(0, c), g = c === -1 ? e[++h] : f.slice(c + 1);
349
+ if (!g || g === "--")
350
350
  return { error: `${a} requires a path` };
351
- let g = h.split(",").map((y) => y.trim()).filter(Boolean);
352
- if (g.length === 0)
351
+ let p = g.split(",").map((y) => y.trim()).filter(Boolean);
352
+ if (p.length === 0)
353
353
  return { error: `${a} requires a path` };
354
- n.push(...g), t = true;
354
+ n.push(...p), t = true;
355
355
  continue;
356
356
  }
357
357
  if (f.startsWith("-"))
358
358
  return { error: `unknown option: ${f}` };
359
- l = p;
359
+ l = h;
360
360
  break;
361
361
  }
362
362
  let d = l === -1 ? [] : e.slice(l);
@@ -410,15 +410,15 @@ var require_dist = __commonJS(function(exports, module) {
410
410
  try {
411
411
  let c = be(o);
412
412
  if (!(o.quiet == null ? J().quiet : o.quiet)) {
413
- let h = `\u25C7 injected env (${Object.keys(c.injected).length})`;
414
- c.loadedPaths.length > 0 && (h += ` from ${c.loadedPaths.join(", ")}`), console.error(h);
413
+ let g = `\u25C7 injected env (${Object.keys(c.injected).length})`;
414
+ c.loadedPaths.length > 0 && (g += ` from ${c.loadedPaths.join(", ")}`), console.error(g);
415
415
  }
416
416
  } catch (c) {
417
417
  console.error(`dotenv: ${c.message}`), process.exitCode = 1;
418
418
  return;
419
419
  }
420
420
  let r = !!process.stdin.isTTY, s = process.platform !== "win32" && !r, i = Ce(t.command[0], t.command.slice(1), { stdio: "inherit", detached: s }), l = new Map, d = 0;
421
- function p(c) {
421
+ function h(c) {
422
422
  if (!(!i.pid || i.exitCode !== null || i.signalCode !== null)) {
423
423
  if (process.platform === "win32") {
424
424
  ve.spawnSync("taskkill", ["/pid", String(i.pid), "/T", "/F"], { stdio: "ignore" });
@@ -442,11 +442,11 @@ var require_dist = __commonJS(function(exports, module) {
442
442
  if (d++, r && process.platform !== "win32" && d === 1)
443
443
  return;
444
444
  if (d > 1) {
445
- p(d === 2 ? "SIGTERM" : "SIGKILL");
445
+ h(d === 2 ? "SIGTERM" : "SIGKILL");
446
446
  return;
447
447
  }
448
448
  }
449
- p(c);
449
+ h(c);
450
450
  };
451
451
  l.set(c, a), process.on(c, a);
452
452
  }
@@ -459,13 +459,13 @@ var require_dist = __commonJS(function(exports, module) {
459
459
  F.exports = K;
460
460
  F === __require.main && K(process.argv.slice(2));
461
461
  });
462
- var j = N();
462
+ var S = N();
463
463
  var qe = X();
464
- module.exports = j;
465
- module.exports.config = j.config;
466
- module.exports.configDotenv = j.configDotenv;
467
- module.exports.parse = j.parse;
468
- module.exports.populate = j.populate;
464
+ module.exports = S;
465
+ module.exports.config = S.config;
466
+ module.exports.configDotenv = S.configDotenv;
467
+ module.exports.parse = S.parse;
468
+ module.exports.populate = S.populate;
469
469
  });
470
470
 
471
471
  // src/load-env.ts
@@ -512,7 +512,7 @@ var createPkcePair = () => {
512
512
  verifier
513
513
  };
514
514
  };
515
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/util.js
515
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/util.js
516
516
  function getEnumValues(entries) {
517
517
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
518
518
  const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
@@ -858,6 +858,18 @@ function prefixIssues(path, issues) {
858
858
  function unwrapMessage(message) {
859
859
  return typeof message === "string" ? message : message?.message;
860
860
  }
861
+ function sizeCaps(defChecks) {
862
+ const caps = [];
863
+ for (const ch of defChecks ?? []) {
864
+ const d = ch._zod.def;
865
+ if (!/_(length|size)$|_equals$/.test(d.check))
866
+ break;
867
+ const max = d.maximum ?? d.length ?? d.size;
868
+ if (max >= 0)
869
+ caps.push([max, ch]);
870
+ }
871
+ return caps;
872
+ }
861
873
  function attachSchema(issues, start, inst) {
862
874
  var _a;
863
875
  for (let i = start;i < issues.length; i++) {
@@ -1055,7 +1067,7 @@ function constantCatch(value) {
1055
1067
  return fn;
1056
1068
  }
1057
1069
 
1058
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/core.js
1070
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/core.js
1059
1071
  var _a;
1060
1072
  var _zodDesc = { value: undefined, enumerable: false };
1061
1073
  var _E = "captureStackTrace" in Error ? Error : null;
@@ -1173,7 +1185,7 @@ function config2(newConfig) {
1173
1185
  Object.assign(globalConfig, newConfig);
1174
1186
  return globalConfig;
1175
1187
  }
1176
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/errors.js
1188
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/errors.js
1177
1189
  function _getMessage() {
1178
1190
  const internals = this._zod;
1179
1191
  internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2));
@@ -1288,7 +1300,7 @@ function formatError(error, mapper = (issue) => issue.message) {
1288
1300
  return fieldErrors;
1289
1301
  }
1290
1302
 
1291
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/parse.js
1303
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/parse.js
1292
1304
  function finalizeParams(callee, params) {
1293
1305
  return { callee: params?.callee ?? callee, Err: params?.Err };
1294
1306
  }
@@ -1435,7 +1447,7 @@ var _safeEncodeAsync = (_Err) => async (schema, value, _ctx) => {
1435
1447
  var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
1436
1448
  return _safeParseAsync(_Err)(schema, value, _ctx);
1437
1449
  };
1438
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/regexes.js
1450
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/regexes.js
1439
1451
  var cuid = /^[cC][0-9a-z]{6,}$/;
1440
1452
  var cuid2 = /^[0-9a-z]+$/;
1441
1453
  var ulid = /^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/;
@@ -1493,7 +1505,7 @@ var _null = /^null$/i;
1493
1505
  var lowercase = /^[^A-Z]*$/;
1494
1506
  var uppercase = /^[^a-z]*$/;
1495
1507
 
1496
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/checks.js
1508
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/checks.js
1497
1509
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
1498
1510
  var _a;
1499
1511
  inst._zod ?? (inst._zod = {});
@@ -1809,7 +1821,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
1809
1821
  };
1810
1822
  });
1811
1823
 
1812
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/doc.js
1824
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/doc.js
1813
1825
  class Doc {
1814
1826
  constructor(args = [], closed = {}) {
1815
1827
  this.content = [];
@@ -1851,14 +1863,14 @@ ${content.join(`
1851
1863
  }
1852
1864
  }
1853
1865
 
1854
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/versions.js
1866
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/versions.js
1855
1867
  var version = {
1856
1868
  major: 4,
1857
1869
  minor: 6,
1858
- patch: 5
1870
+ patch: 7
1859
1871
  };
1860
1872
 
1861
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/schemas.js
1873
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/schemas.js
1862
1874
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
1863
1875
  var _a;
1864
1876
  inst ?? (inst = {});
@@ -2424,6 +2436,29 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
2424
2436
  return payload;
2425
2437
  };
2426
2438
  });
2439
+ function capSize(inst, size) {
2440
+ const caps = sizeCaps(inst._zod.def.checks);
2441
+ if (!caps.length)
2442
+ return;
2443
+ const cap = Math.min(...caps.map((c) => c[0]));
2444
+ const parse = inst._zod.parse;
2445
+ inst._zod.parse = (payload, ctx) => {
2446
+ const n = size(payload.value);
2447
+ if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
2448
+ for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
2449
+ if (n > max && ch._zod.def.when(payload)) {
2450
+ const start = payload.issues.length;
2451
+ ch._zod.check(payload);
2452
+ payload.issues[start].continue = false;
2453
+ attachSchema(payload.issues, start, inst);
2454
+ return payload;
2455
+ }
2456
+ }
2457
+ }
2458
+ return parse(payload, ctx);
2459
+ };
2460
+ }
2461
+ var arraySize = (input) => Array.isArray(input) ? input.length : -1;
2427
2462
  function handleArrayResult(result, final, index) {
2428
2463
  if (result.issues.length) {
2429
2464
  final.issues.push(...prefixIssues(index, result.issues));
@@ -2467,6 +2502,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
2467
2502
  }
2468
2503
  return payload;
2469
2504
  };
2505
+ capSize(inst, arraySize);
2470
2506
  });
2471
2507
  function handlePropertyResult(result, final, key, input, optin, optout) {
2472
2508
  const isPresent = key in input;
@@ -3249,7 +3285,7 @@ function handleRefineResult(result, payload, input, inst) {
3249
3285
  payload.issues.push(issue(_iss));
3250
3286
  }
3251
3287
  }
3252
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/memoizer.js
3288
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/memoizer.js
3253
3289
  class $ZodCyclicError extends Error {
3254
3290
  constructor() {
3255
3291
  super(`Cannot parse a reference cycle that closes through a transform`);
@@ -3518,7 +3554,7 @@ function isBackEdge(ctx, value) {
3518
3554
  const backEdges = ctx[STATE]?.backEdges;
3519
3555
  return backEdges !== undefined && isRef(value) && backEdges.has(value);
3520
3556
  }
3521
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/locales/en.js
3557
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/locales/en.js
3522
3558
  var error = () => {
3523
3559
  const Sizable = {
3524
3560
  string: { unit: "characters", verb: "to have" },
@@ -3640,7 +3676,7 @@ function en_default() {
3640
3676
  localeError: error()
3641
3677
  };
3642
3678
  }
3643
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/registries.js
3679
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/registries.js
3644
3680
  var _a2;
3645
3681
  class $ZodRegistry {
3646
3682
  constructor() {
@@ -3687,7 +3723,7 @@ function registry() {
3687
3723
  }
3688
3724
  (_a2 = globalThis).__zod_globalRegistry ?? (_a2.__zod_globalRegistry = registry());
3689
3725
  var globalRegistry = globalThis.__zod_globalRegistry;
3690
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/api.js
3726
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/api.js
3691
3727
  function snapshotChecks(def) {
3692
3728
  if (def.checks)
3693
3729
  def.checks = [...def.checks];
@@ -4141,7 +4177,7 @@ function _check(fn, params) {
4141
4177
  ch._zod.check = fn;
4142
4178
  return ch;
4143
4179
  }
4144
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/to-json-schema.js
4180
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/to-json-schema.js
4145
4181
  function assignProps(target, ...sources) {
4146
4182
  for (const source of sources) {
4147
4183
  for (const key of Reflect.ownKeys(source)) {
@@ -4664,7 +4700,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) =
4664
4700
  extractDefs(ctx, schema);
4665
4701
  return finalize(ctx, schema);
4666
4702
  };
4667
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/json-schema-processors.js
4703
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/core/json-schema-processors.js
4668
4704
  var narrowMin = (agg, key, value) => {
4669
4705
  if (agg[key] === undefined || value > agg[key])
4670
4706
  agg[key] = value;
@@ -5093,7 +5129,7 @@ var optionalProcessor = (schema, ctx, _json, params) => {
5093
5129
  const seen = ctx.seen.get(schema);
5094
5130
  seen.ref = def.innerType;
5095
5131
  };
5096
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/errors.js
5132
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/classic/errors.js
5097
5133
  var _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);
5098
5134
  function _lazyMethod(proto, key, make) {
5099
5135
  Object.defineProperty(proto, key, {
@@ -5138,7 +5174,7 @@ var ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer2, undefi
5138
5174
  Parent: Error
5139
5175
  });
5140
5176
 
5141
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/parse.js
5177
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/classic/parse.js
5142
5178
  var parse2 = /* @__PURE__ */ _parse(ZodRealError);
5143
5179
  var parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
5144
5180
  var safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -5152,7 +5188,7 @@ var safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError);
5152
5188
  var safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
5153
5189
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
5154
5190
 
5155
- // ../../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/schemas.js
5191
+ // ../../../node_modules/.bun/zod@4.6.7/node_modules/zod/v4/classic/schemas.js
5156
5192
  function _ensureDefaultLocale() {
5157
5193
  if (!globalConfig.localeError)
5158
5194
  config2(en_default());
@@ -6827,6 +6863,45 @@ Usage:
6827
6863
  et lucky-draw pre-draw --event-id <id> --prize-count <n>
6828
6864
  et lucky-draw participants replace --event-id <id> (--participants <json-array> | --participants-file <path>) --allow-state-change --target <same-event-id>
6829
6865
  et lucky-draw participants list --event-id <id> [--page <n>] [--per-page <n>]
6866
+ et passport overview --event-id <id>
6867
+ et passport mine --event-id <id>
6868
+ et passport login-options --event-id <id>
6869
+ et passport export --event-id <id>
6870
+ et passport settings update --event-id <id> --settings-json <json>
6871
+ et passport station upsert --event-id <id> --station-json <json>
6872
+ et passport station hidden --event-id <id> --station-id <id> --hidden <true|false>
6873
+ et passport station archive --event-id <id> --station-id <id> --allow-state-change --target <same-event-id>
6874
+ et passport station print-get --event-id <id> --station-id <id>
6875
+ et passport station print-issue --event-id <id> --station-id <id> --expected-printed-qr-version <n>
6876
+ et passport station print-revoke --event-id <id> --station-id <id> --expected-printed-qr-version <n> --allow-state-change --target <same-event-id>
6877
+ et passport station start-qr --event-id <id> --station-id <id>
6878
+ et passport station qr-status --event-id <id> --session-id <id>
6879
+ et passport collect --event-id <id> --station-id <id> --profile-code <code> [--points <n>]
6880
+ et passport claim --event-id <id> --code <code>
6881
+ et passport participant search --event-id <id> [--query <text>]
6882
+ et passport participant detail --event-id <id> --participant-id <id>
6883
+ et passport stamp correct --event-id <id> --station-id <id> --participant-id <id> --stamped <true|false> --reason <text> [--points <n>] --allow-state-change --target <same-event-id>
6884
+ et passport prize upsert --event-id <id> --prize-json <json>
6885
+ et passport prize archive --event-id <id> --prize-id <id> --allow-state-change --target <same-event-id>
6886
+ et passport redemption create --event-id <id> --participant-id <id> --prize-id <id>
6887
+ et passport redemption reverse --event-id <id> --redemption-id <id> --reason <text> --allow-state-change --target <same-event-id>
6888
+
6889
+ Event Passport:
6890
+ Uses the same typed procedures and event permissions as the web app.
6891
+ Station collection modes: SELF_SCAN, STAFF_SCAN, STAFF_SCORE.
6892
+ Include collection.maxPoints only for STAFF_SCORE; zero is a valid score.
6893
+ Omit collection on an existing station to preserve its current mode.
6894
+ Station JSON supports id/name/description/location/imageKey/order/opensAt/closesAt/collection.
6895
+ Date-time fields are ISO strings or null; order defaults to zero.
6896
+ Settings JSON requires linkedDrawEventId, luckyDrawStampThreshold, prizeStampThreshold,
6897
+ maxRedemptionsPerParticipant; optional loginMethods is {emailOtp,google,guest}.
6898
+ Keep email OTP or Google enabled for guest recovery. Omit loginMethods to preserve it.
6899
+ Printed QR issue/revoke requires the last observed print version; stale versions conflict.
6900
+ claim scans a station QR; collect scans a participant profile QR as an event operator.
6901
+ Repeat scans never add a second stamp or change its original points.
6902
+ Destructive corrections, archive, reverse and print revoke require explicit target confirmation.
6903
+ Points are scores only; existing stamp-based Lucky Draw and prize thresholds still apply.
6904
+ Guest enrollment and account-linking require the browser; CLI uses existing device-approved auth.
6830
6905
 
6831
6906
  Lucky draw:
6832
6907
  pre-draw immediately saves winners for the next unassigned prizes in order.
@@ -6897,6 +6972,334 @@ var writeError = (runtime, error) => {
6897
6972
  runtime.stderr.write(serialize({ ok: false, error: { code: errorCode(error), message } }));
6898
6973
  };
6899
6974
 
6975
+ // src/commands/passport.ts
6976
+ var flag = (flags, name, required = true) => {
6977
+ const value = flags.get(name);
6978
+ if (value === true || required && !value)
6979
+ throw new CliUsageError(`--${name} requires a value.`);
6980
+ return value;
6981
+ };
6982
+ var requiredFlag = (flags, name) => {
6983
+ const value = flag(flags, name);
6984
+ if (!value)
6985
+ throw new CliUsageError(`--${name} is required.`);
6986
+ return value;
6987
+ };
6988
+ var integer2 = (value, name, minimum = 0) => {
6989
+ const parsed = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
6990
+ if (typeof parsed !== "number" || !Number.isSafeInteger(parsed) || parsed < minimum || parsed > 2147483647) {
6991
+ throw new CliUsageError(`${name} must be a whole number from ${minimum} to 2147483647.`);
6992
+ }
6993
+ return parsed;
6994
+ };
6995
+ var boolean3 = (value, name) => {
6996
+ if (value === true || value === "true")
6997
+ return true;
6998
+ if (value === false || value === "false")
6999
+ return false;
7000
+ throw new CliUsageError(`${name} must be true or false.`);
7001
+ };
7002
+ var text = (value, name, maximum) => {
7003
+ if (typeof value !== "string" || !value.trim() || value.trim().length > maximum)
7004
+ throw new CliUsageError(`${name} must be a non-empty string of at most ${maximum} characters.`);
7005
+ return value.trim();
7006
+ };
7007
+ var nullableText = (value, name, maximum) => {
7008
+ if (value == null)
7009
+ return null;
7010
+ if (typeof value !== "string" || value.trim().length > maximum)
7011
+ throw new CliUsageError(`${name} must be a string of at most ${maximum} characters or null.`);
7012
+ return value.trim();
7013
+ };
7014
+ var object2 = (value, name) => {
7015
+ if (typeof value !== "object" || value === null || Array.isArray(value))
7016
+ throw new CliUsageError(`${name} must be an object.`);
7017
+ return Object.fromEntries(Object.entries(value));
7018
+ };
7019
+ var json = (value, name) => {
7020
+ try {
7021
+ const parsed = JSON.parse(value);
7022
+ return object2(parsed, name);
7023
+ } catch (error) {
7024
+ if (error instanceof CliUsageError)
7025
+ throw error;
7026
+ throw new CliUsageError(`${name} must be valid JSON.`);
7027
+ }
7028
+ };
7029
+ var keys = (value, allowed, name) => {
7030
+ if (Object.keys(value).some((key) => !allowed.includes(key)))
7031
+ throw new CliUsageError(`${name} contains unsupported fields.`);
7032
+ };
7033
+ var date2 = (value, name) => {
7034
+ if (value == null)
7035
+ return null;
7036
+ if (typeof value !== "string" || !/^\d{4}-\d\d-\d\dT/.test(value))
7037
+ throw new CliUsageError(`${name} must be an ISO date-time or null.`);
7038
+ const parsed = new Date(value);
7039
+ if (Number.isNaN(parsed.getTime()))
7040
+ throw new CliUsageError(`${name} must be a valid ISO date-time.`);
7041
+ return parsed;
7042
+ };
7043
+ var parsePassportStationInput = (raw, eventId) => {
7044
+ const value = json(raw, "--station-json");
7045
+ keys(value, [
7046
+ "id",
7047
+ "name",
7048
+ "description",
7049
+ "location",
7050
+ "imageKey",
7051
+ "order",
7052
+ "opensAt",
7053
+ "closesAt",
7054
+ "collection"
7055
+ ], "Station");
7056
+ let collection;
7057
+ if (value.collection !== undefined) {
7058
+ const item = object2(value.collection, "collection");
7059
+ if (item.collectionMode === "STAFF_SCORE") {
7060
+ keys(item, ["collectionMode", "maxPoints"], "collection");
7061
+ collection = {
7062
+ collectionMode: "STAFF_SCORE",
7063
+ maxPoints: integer2(item.maxPoints, "maxPoints")
7064
+ };
7065
+ } else if (item.collectionMode === "SELF_SCAN" || item.collectionMode === "STAFF_SCAN") {
7066
+ keys(item, ["collectionMode"], "collection");
7067
+ collection = { collectionMode: item.collectionMode };
7068
+ } else
7069
+ throw new CliUsageError("collectionMode must be SELF_SCAN, STAFF_SCAN or STAFF_SCORE.");
7070
+ }
7071
+ return {
7072
+ eventId,
7073
+ ...value.id === undefined ? {} : { id: text(value.id, "id", 200) },
7074
+ name: text(value.name, "name", 100),
7075
+ description: nullableText(value.description, "description", 1000),
7076
+ location: nullableText(value.location, "location", 200),
7077
+ imageKey: nullableText(value.imageKey, "imageKey", 2048),
7078
+ order: integer2(value.order ?? 0, "order"),
7079
+ opensAt: date2(value.opensAt, "opensAt"),
7080
+ closesAt: date2(value.closesAt, "closesAt"),
7081
+ ...collection ? { collection } : {}
7082
+ };
7083
+ };
7084
+ var parsePassportSettingsInput = (raw, eventId) => {
7085
+ const value = json(raw, "--settings-json");
7086
+ keys(value, [
7087
+ "luckyDrawStampThreshold",
7088
+ "prizeStampThreshold",
7089
+ "maxRedemptionsPerParticipant",
7090
+ "linkedDrawEventId",
7091
+ "loginMethods"
7092
+ ], "Settings");
7093
+ const threshold = (item, name) => item === null ? null : integer2(item, name, 1);
7094
+ let loginMethods;
7095
+ if (value.loginMethods !== undefined) {
7096
+ const methods = object2(value.loginMethods, "loginMethods");
7097
+ keys(methods, ["emailOtp", "google", "guest"], "loginMethods");
7098
+ if (typeof methods.emailOtp !== "boolean" || typeof methods.google !== "boolean" || typeof methods.guest !== "boolean")
7099
+ throw new CliUsageError("loginMethods values must be JSON booleans.");
7100
+ loginMethods = {
7101
+ emailOtp: methods.emailOtp,
7102
+ google: methods.google,
7103
+ guest: methods.guest
7104
+ };
7105
+ if (!loginMethods.emailOtp && !loginMethods.google)
7106
+ throw new CliUsageError("Keep email OTP or Google available for recovery.");
7107
+ }
7108
+ if (value.linkedDrawEventId === undefined)
7109
+ throw new CliUsageError("linkedDrawEventId is required (use null to disable).");
7110
+ return {
7111
+ eventId,
7112
+ luckyDrawStampThreshold: threshold(value.luckyDrawStampThreshold, "luckyDrawStampThreshold"),
7113
+ prizeStampThreshold: threshold(value.prizeStampThreshold, "prizeStampThreshold"),
7114
+ maxRedemptionsPerParticipant: integer2(value.maxRedemptionsPerParticipant, "maxRedemptionsPerParticipant", 1),
7115
+ linkedDrawEventId: value.linkedDrawEventId === null ? null : text(value.linkedDrawEventId, "linkedDrawEventId", 200),
7116
+ ...loginMethods ? { loginMethods } : {}
7117
+ };
7118
+ };
7119
+ var runPassportCommand = async (input) => {
7120
+ const { flags, positionals } = input;
7121
+ const action = positionals.slice(1).join(" ");
7122
+ const allowed = ["event-id"];
7123
+ const eventId = requiredFlag(flags, "event-id");
7124
+ const event = { eventId };
7125
+ const station = () => ({
7126
+ eventId,
7127
+ stationId: requiredFlag(flags, "station-id")
7128
+ });
7129
+ const version = () => integer2(requiredFlag(flags, "expected-printed-qr-version"), "--expected-printed-qr-version");
7130
+ const confirm = () => {
7131
+ allowed.push("allow-state-change", "target");
7132
+ if (flags.get("allow-state-change") !== true || requiredFlag(flags, "target") !== eventId)
7133
+ throw new CliUsageError("This operation requires --allow-state-change and --target exactly equal to --event-id.");
7134
+ };
7135
+ let operation;
7136
+ switch (action) {
7137
+ case "overview":
7138
+ operation = () => api2.event.passport.getPassportOverview.query(event);
7139
+ break;
7140
+ case "mine":
7141
+ operation = () => api2.event.passport.getMyPassport.query(event);
7142
+ break;
7143
+ case "login-options":
7144
+ operation = () => api2.event.passport.getPassportLoginOptions.query(event);
7145
+ break;
7146
+ case "export":
7147
+ operation = () => api2.event.passport.getPassportExportData.query(event);
7148
+ break;
7149
+ case "settings update": {
7150
+ allowed.push("settings-json");
7151
+ const payload = parsePassportSettingsInput(requiredFlag(flags, "settings-json"), eventId);
7152
+ operation = () => api2.event.passport.updatePassportSettings.mutate(payload);
7153
+ break;
7154
+ }
7155
+ case "station upsert": {
7156
+ allowed.push("station-json");
7157
+ const payload = parsePassportStationInput(requiredFlag(flags, "station-json"), eventId);
7158
+ operation = () => api2.event.passport.upsertPassportStation.mutate(payload);
7159
+ break;
7160
+ }
7161
+ case "station print-get": {
7162
+ allowed.push("station-id");
7163
+ const payload = station();
7164
+ operation = () => api2.event.passport.getStationPrintQr.query(payload);
7165
+ break;
7166
+ }
7167
+ case "station print-issue":
7168
+ case "station print-revoke": {
7169
+ allowed.push("station-id", "expected-printed-qr-version");
7170
+ const payload = { ...station(), expectedPrintedQrVersion: version() };
7171
+ if (action === "station print-revoke")
7172
+ confirm();
7173
+ operation = action === "station print-issue" ? () => api2.event.passport.issueStationPrintQr.mutate(payload) : () => api2.event.passport.revokeStationPrintQr.mutate(payload);
7174
+ break;
7175
+ }
7176
+ case "station archive": {
7177
+ allowed.push("station-id");
7178
+ confirm();
7179
+ const payload = station();
7180
+ operation = () => api2.event.passport.archivePassportStation.mutate(payload);
7181
+ break;
7182
+ }
7183
+ case "station hidden": {
7184
+ allowed.push("station-id", "hidden");
7185
+ const payload = {
7186
+ ...station(),
7187
+ hidden: boolean3(requiredFlag(flags, "hidden"), "--hidden")
7188
+ };
7189
+ operation = () => api2.event.passport.setPassportStationHidden.mutate(payload);
7190
+ break;
7191
+ }
7192
+ case "station start-qr": {
7193
+ allowed.push("station-id");
7194
+ const payload = station();
7195
+ operation = () => api2.event.passport.startStationQr.mutate(payload);
7196
+ break;
7197
+ }
7198
+ case "station qr-status": {
7199
+ allowed.push("session-id");
7200
+ const payload = { eventId, sessionId: requiredFlag(flags, "session-id") };
7201
+ operation = () => api2.event.passport.getStationQrStatus.query(payload);
7202
+ break;
7203
+ }
7204
+ case "collect": {
7205
+ allowed.push("station-id", "profile-code", "points");
7206
+ const points = flag(flags, "points", false);
7207
+ const payload = {
7208
+ ...station(),
7209
+ profileCode: requiredFlag(flags, "profile-code"),
7210
+ ...points === undefined ? {} : { points: integer2(points, "--points") }
7211
+ };
7212
+ operation = () => api2.event.passport.collectPassportStampByStaff.mutate(payload);
7213
+ break;
7214
+ }
7215
+ case "claim": {
7216
+ allowed.push("code");
7217
+ const payload = { eventId, code: requiredFlag(flags, "code") };
7218
+ operation = () => api2.event.passport.claimPassportStamp.mutate(payload);
7219
+ break;
7220
+ }
7221
+ case "stamp correct": {
7222
+ allowed.push("station-id", "participant-id", "stamped", "reason", "points");
7223
+ confirm();
7224
+ const points = flag(flags, "points", false);
7225
+ const payload = {
7226
+ ...station(),
7227
+ participantId: requiredFlag(flags, "participant-id"),
7228
+ stamped: boolean3(requiredFlag(flags, "stamped"), "--stamped"),
7229
+ reason: requiredFlag(flags, "reason"),
7230
+ ...points === undefined ? {} : { points: integer2(points, "--points") }
7231
+ };
7232
+ operation = () => api2.event.passport.correctPassportStamp.mutate(payload);
7233
+ break;
7234
+ }
7235
+ case "participant detail": {
7236
+ allowed.push("participant-id");
7237
+ const payload = {
7238
+ eventId,
7239
+ participantId: requiredFlag(flags, "participant-id")
7240
+ };
7241
+ operation = () => api2.event.passport.getPassportParticipantDetail.query(payload);
7242
+ break;
7243
+ }
7244
+ case "participant search": {
7245
+ allowed.push("query");
7246
+ const payload = { eventId, query: flag(flags, "query", false) ?? "" };
7247
+ operation = () => api2.event.passport.searchPassportParticipants.query(payload);
7248
+ break;
7249
+ }
7250
+ case "prize upsert": {
7251
+ allowed.push("prize-json");
7252
+ const value = json(requiredFlag(flags, "prize-json"), "--prize-json");
7253
+ keys(value, ["id", "name", "description", "stock", "order"], "Prize");
7254
+ const payload = {
7255
+ eventId,
7256
+ ...value.id === undefined ? {} : { id: text(value.id, "id", 200) },
7257
+ name: text(value.name, "name", 100),
7258
+ description: nullableText(value.description, "description", 1000),
7259
+ stock: integer2(value.stock, "stock"),
7260
+ order: integer2(value.order ?? 0, "order")
7261
+ };
7262
+ operation = () => api2.event.passport.upsertPassportPrize.mutate(payload);
7263
+ break;
7264
+ }
7265
+ case "prize archive": {
7266
+ allowed.push("prize-id");
7267
+ confirm();
7268
+ const payload = { eventId, prizeId: requiredFlag(flags, "prize-id") };
7269
+ operation = () => api2.event.passport.archivePassportPrize.mutate(payload);
7270
+ break;
7271
+ }
7272
+ case "redemption create": {
7273
+ allowed.push("prize-id", "participant-id");
7274
+ const payload = {
7275
+ eventId,
7276
+ prizeId: requiredFlag(flags, "prize-id"),
7277
+ participantId: requiredFlag(flags, "participant-id")
7278
+ };
7279
+ operation = () => api2.event.passport.redeemPassportPrize.mutate(payload);
7280
+ break;
7281
+ }
7282
+ case "redemption reverse": {
7283
+ allowed.push("redemption-id", "reason");
7284
+ confirm();
7285
+ const payload = {
7286
+ eventId,
7287
+ redemptionId: requiredFlag(flags, "redemption-id"),
7288
+ reason: requiredFlag(flags, "reason")
7289
+ };
7290
+ operation = () => api2.event.passport.reversePassportRedemption.mutate(payload);
7291
+ break;
7292
+ }
7293
+ default:
7294
+ throw new CliUsageError("Unknown passport command. Run et --help for supported commands.");
7295
+ }
7296
+ const unknown = [...flags.keys()].filter((key) => key !== "api-url" && !allowed.includes(key));
7297
+ if (unknown.length)
7298
+ throw new CliUsageError(`Unknown option(s): ${unknown.map((key) => `--${key}`).join(", ")}.`);
7299
+ await input.authenticate();
7300
+ writeSuccess(input.runtime, await operation());
7301
+ };
7302
+
6900
7303
  // src/cli.ts
6901
7304
  var getInstalledCliVersion = () => {
6902
7305
  try {
@@ -7119,6 +7522,15 @@ var runCommand = async (parsed, runtime, credentialStore, apiBaseUrl, configureA
7119
7522
  writeSuccess(runtime, { version: cliVersion });
7120
7523
  return;
7121
7524
  }
7525
+ if (group === "passport") {
7526
+ await runPassportCommand({
7527
+ positionals: parsed.positionals,
7528
+ flags: parsed.flags,
7529
+ runtime,
7530
+ authenticate: ensureAuthentication
7531
+ });
7532
+ return;
7533
+ }
7122
7534
  if (group === "auth" && action === "login" && subAction === undefined) {
7123
7535
  assertPositionalCount(parsed, 2);
7124
7536
  assertOnlyFlags(parsed, ["no-browser"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/event-tech",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Event Tech CLI for managing Event Tech resources through the Go Labs API.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "@trpc/client": "^11.19.0",
20
- "dotenv": "^18.0.7",
20
+ "dotenv": "^18.0.8",
21
21
  "superjson": "^2.2.6"
22
22
  },
23
23
  "engines": {