@go-labs-sg/event-tech 1.1.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.
- package/README.md +52 -0
- package/dist/index.js +376 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,6 +99,58 @@ 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
|
+
|
|
102
154
|
### Deprecated event types
|
|
103
155
|
|
|
104
156
|
Scavenger Hunt (Amazing Race) and Gardens by the Bay are deprecated and frozen.
|
package/dist/index.js
CHANGED
|
@@ -6863,6 +6863,45 @@ Usage:
|
|
|
6863
6863
|
et lucky-draw pre-draw --event-id <id> --prize-count <n>
|
|
6864
6864
|
et lucky-draw participants replace --event-id <id> (--participants <json-array> | --participants-file <path>) --allow-state-change --target <same-event-id>
|
|
6865
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.
|
|
6866
6905
|
|
|
6867
6906
|
Lucky draw:
|
|
6868
6907
|
pre-draw immediately saves winners for the next unassigned prizes in order.
|
|
@@ -6933,6 +6972,334 @@ var writeError = (runtime, error) => {
|
|
|
6933
6972
|
runtime.stderr.write(serialize({ ok: false, error: { code: errorCode(error), message } }));
|
|
6934
6973
|
};
|
|
6935
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
|
+
|
|
6936
7303
|
// src/cli.ts
|
|
6937
7304
|
var getInstalledCliVersion = () => {
|
|
6938
7305
|
try {
|
|
@@ -7155,6 +7522,15 @@ var runCommand = async (parsed, runtime, credentialStore, apiBaseUrl, configureA
|
|
|
7155
7522
|
writeSuccess(runtime, { version: cliVersion });
|
|
7156
7523
|
return;
|
|
7157
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
|
+
}
|
|
7158
7534
|
if (group === "auth" && action === "login" && subAction === undefined) {
|
|
7159
7535
|
assertPositionalCount(parsed, 2);
|
|
7160
7536
|
assertOnlyFlags(parsed, ["no-browser"]);
|