@helix3/helix-cli 0.1.13-helix3.69 → 0.1.13-helix3.71

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.
@@ -0,0 +1,123 @@
1
+ /** 2–80 chars, lowercase letters/digits/`_`/`-`, starting alphanumeric. */
2
+ export declare const ACHIEVEMENT_KEY_PATTERN: RegExp;
3
+ /**
4
+ * WHO may award the badge — the trust marker a player and the platform UI read.
5
+ * `platform` is first-party code only; it is in the list because the backend
6
+ * accepts it, not because a world should use it (see `assertUnlockModeForWorld`).
7
+ */
8
+ export declare const ACHIEVEMENT_UNLOCK_MODES: readonly ["room", "criteria", "platform"];
9
+ export type AchievementUnlockMode = (typeof ACHIEVEMENT_UNLOCK_MODES)[number];
10
+ export declare const ACHIEVEMENT_CRITERIA_SIGNALS: readonly ["datastore", "iwp", "analytics", "playtime"];
11
+ export type AchievementCriteriaSignal = (typeof ACHIEVEMENT_CRITERIA_SIGNALS)[number];
12
+ export declare const ACHIEVEMENT_CRITERIA_OPS: readonly ["gte", "lte", "eq"];
13
+ export type AchievementCriteriaOp = (typeof ACHIEVEMENT_CRITERIA_OPS)[number];
14
+ export declare const ACHIEVEMENT_CRITERIA_METRICS: readonly ["count", "lix"];
15
+ export type AchievementCriteriaMetric = (typeof ACHIEVEMENT_CRITERIA_METRICS)[number];
16
+ /**
17
+ * The only two documents a `datastore` criteria may read, and WHICH ONE IS THE
18
+ * TRUST DECISION: `mp:player:{userId}` is the room's flushed persistent
19
+ * playerVars (room-only writable ⇒ server-authoritative), `player:{userId}` is
20
+ * the player's own client-written save (forgeable by its owner, accepted
21
+ * deliberately — it is how a single-player world unlocks anything).
22
+ */
23
+ export declare const DATA_STORE_CRITERIA_KEY_TEMPLATES: readonly ["player:{userId}", "mp:player:{userId}"];
24
+ export type DataStoreCriteriaKeyTemplate = (typeof DATA_STORE_CRITERIA_KEY_TEMPLATES)[number];
25
+ /** A `datastore` criteria's `field`: a dot-path of letters, digits and underscores. */
26
+ export declare const DATA_STORE_CRITERIA_FIELD_PATTERN: RegExp;
27
+ /** Backend caps (`ACHIEVEMENT_ICON_MAX_BYTES` / `ACHIEVEMENT_MESH_MAX_BYTES` defaults). */
28
+ export declare const ACHIEVEMENT_ICON_MAX_BYTES: number;
29
+ export declare const ACHIEVEMENT_TROPHY_MAX_BYTES: number;
30
+ /** Smallest square an icon can be and still read as a graphic on a plaque. */
31
+ export declare const MIN_ICON_EDGE = 16;
32
+ /**
33
+ * Per-channel standard deviation below which the backend treats an image as one
34
+ * flat colour. Not zero — a real icon that has been through lossy encoding
35
+ * carries a little noise.
36
+ */
37
+ export declare const MIN_ICON_STDDEV = 1;
38
+ export declare const isAchievementKey: (value: unknown) => value is string;
39
+ /** Content type for the required `image` part — the 2D badge graphic. */
40
+ export declare function iconContentTypeFromExtension(file: string): string;
41
+ /**
42
+ * What the backend's `assertValidAchievementIcon` checks, mirrored so a
43
+ * placeholder fails in a second instead of after an upload + a moderation pass.
44
+ * The two rejections are the two placeholders creators actually send: an image
45
+ * too small to read, and a single flat colour. Deliberately NOT a quality
46
+ * judgement — a two-tone glyph or a flat logo on a plate passes.
47
+ */
48
+ export declare function assertIconLooksReal(bytes: Uint8Array, file: string): Promise<void>;
49
+ export type AchievementCriteria = {
50
+ signal: AchievementCriteriaSignal;
51
+ op: AchievementCriteriaOp;
52
+ value: number;
53
+ eventName?: string;
54
+ key?: DataStoreCriteriaKeyTemplate;
55
+ field?: string;
56
+ metric?: AchievementCriteriaMetric;
57
+ };
58
+ export type AchievementCriteriaInput = {
59
+ signal?: string;
60
+ op?: string;
61
+ value?: number;
62
+ eventName?: string;
63
+ key?: string;
64
+ field?: string;
65
+ metric?: string;
66
+ };
67
+ /** True when any criteria field was supplied — i.e. the caller means `criteria`. */
68
+ export declare function hasCriteriaInput(input: AchievementCriteriaInput | undefined): boolean;
69
+ /**
70
+ * Validate + normalize the criteria the way the backend's `normalizeCriteria`
71
+ * does, and throw the same failures. Returns the exact object sent as the
72
+ * multipart `criteria` JSON string — no key the caller did not set.
73
+ */
74
+ export declare function buildAchievementCriteria(input: AchievementCriteriaInput): AchievementCriteria;
75
+ /** One-line human summary of a stored criteria — the `list` column and the register echo. */
76
+ export declare function formatAchievementCriteria(criteria: AchievementCriteria | null | undefined): string;
77
+ export type AchievementRegistrationInput = {
78
+ key: string;
79
+ name: string;
80
+ description?: string;
81
+ points?: number;
82
+ hidden?: boolean;
83
+ unlockMode?: string;
84
+ criteria?: AchievementCriteriaInput;
85
+ };
86
+ export type AchievementRegistrationFields = {
87
+ key: string;
88
+ name: string;
89
+ description?: string;
90
+ points?: number;
91
+ hidden?: boolean;
92
+ unlockMode: AchievementUnlockMode;
93
+ criteria?: AchievementCriteria;
94
+ };
95
+ export type AchievementRegistrationPlan = {
96
+ fields: AchievementRegistrationFields;
97
+ warnings: string[];
98
+ };
99
+ /**
100
+ * Resolve the trust marker. The backend's DTO defaults to `platform` because the
101
+ * ADMIN path (worldId omitted) is the one that needs it; for a WORLD
102
+ * registration `platform` is a mislabel — nothing in a world is first-party
103
+ * code. So this CLI always sends an explicit mode: `criteria` when a condition
104
+ * was declared, otherwise `room`, the only thing a world can actually award
105
+ * (the `awardAchievement` rule effect).
106
+ */
107
+ export declare function resolveUnlockMode(explicit: string | undefined, hasCriteria: boolean): AchievementUnlockMode;
108
+ /**
109
+ * Build the multipart text fields, applying every local rule first. Keys the
110
+ * caller did not set are OMITTED rather than sent empty — an empty description
111
+ * and no description are the same row, and sending "" would overwrite nothing
112
+ * while looking like intent.
113
+ */
114
+ export declare function buildAchievementRegistration(input: AchievementRegistrationInput): AchievementRegistrationPlan;
115
+ export type AchievementUpdateInput = {
116
+ name?: string;
117
+ description?: string;
118
+ points?: number;
119
+ hidden?: boolean;
120
+ active?: boolean;
121
+ };
122
+ /** Validate a PATCH body locally and refuse an empty one (a no-op round trip that reads as success). */
123
+ export declare function buildAchievementUpdate(input: AchievementUpdateInput): AchievementUpdateInput;
@@ -0,0 +1,400 @@
1
+ "use strict";
2
+ // Pure, network-free helpers behind `helix achievement …` — the registration
3
+ // vocabulary (key charset, unlock modes, the closed criteria grammar), the icon
4
+ // sniffing, and the multipart field builder. Split from the HTTP flow in lib.ts
5
+ // for the same reason item.ts is: every rule below is testable without mocking a
6
+ // server, and every one of them costs a round trip if it only fails remotely.
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.isAchievementKey = exports.MIN_ICON_STDDEV = exports.MIN_ICON_EDGE = exports.ACHIEVEMENT_TROPHY_MAX_BYTES = exports.ACHIEVEMENT_ICON_MAX_BYTES = exports.DATA_STORE_CRITERIA_FIELD_PATTERN = exports.DATA_STORE_CRITERIA_KEY_TEMPLATES = exports.ACHIEVEMENT_CRITERIA_METRICS = exports.ACHIEVEMENT_CRITERIA_OPS = exports.ACHIEVEMENT_CRITERIA_SIGNALS = exports.ACHIEVEMENT_UNLOCK_MODES = exports.ACHIEVEMENT_KEY_PATTERN = void 0;
42
+ exports.iconContentTypeFromExtension = iconContentTypeFromExtension;
43
+ exports.assertIconLooksReal = assertIconLooksReal;
44
+ exports.hasCriteriaInput = hasCriteriaInput;
45
+ exports.buildAchievementCriteria = buildAchievementCriteria;
46
+ exports.formatAchievementCriteria = formatAchievementCriteria;
47
+ exports.resolveUnlockMode = resolveUnlockMode;
48
+ exports.buildAchievementRegistration = buildAchievementRegistration;
49
+ exports.buildAchievementUpdate = buildAchievementUpdate;
50
+ // ---------------------------------------------------------------------------
51
+ // The registration vocabulary
52
+ // ---------------------------------------------------------------------------
53
+ //
54
+ // !! MIRROR — KEEP IN LOCKSTEP WITH THE BACKEND !!
55
+ //
56
+ // AUTHORITY: helix-backend-api → src/achievements/dtos/achievement.dtos.ts
57
+ // (`KEY_PATTERN`, `CreateAchievementRequestDto`) and
58
+ // src/database/enums/achievement-unlock-mode.enum.ts +
59
+ // achievement-criteria.enum.ts. The DSL side mirrors the SAME key
60
+ // charset in helix-manifest/schema/manifest-v0.3.schema.json
61
+ // (`awardAchievement.key`) — three copies, one charset.
62
+ //
63
+ // This is a LOCAL FAST PATH, never the authority. It exists so a malformed key
64
+ // or an incoherent criteria fails before an 8 MB icon is uploaded and pushed
65
+ // through moderation — nothing more. Two properties keep a stale copy harmless:
66
+ // the CLI never invents a value (every flag is matched EXACTLY against these
67
+ // lists), and the server is always the last word — its 400 enumerates the real
68
+ // vocabulary and is surfaced verbatim (ApiError.render()). `achievement.spec.ts`
69
+ // pins the lists, so any edit is a reviewed diff rather than silent drift.
70
+ /** 2–80 chars, lowercase letters/digits/`_`/`-`, starting alphanumeric. */
71
+ exports.ACHIEVEMENT_KEY_PATTERN = /^[a-z0-9][a-z0-9_-]{1,79}$/;
72
+ /**
73
+ * WHO may award the badge — the trust marker a player and the platform UI read.
74
+ * `platform` is first-party code only; it is in the list because the backend
75
+ * accepts it, not because a world should use it (see `assertUnlockModeForWorld`).
76
+ */
77
+ exports.ACHIEVEMENT_UNLOCK_MODES = ['room', 'criteria', 'platform'];
78
+ exports.ACHIEVEMENT_CRITERIA_SIGNALS = ['datastore', 'iwp', 'analytics', 'playtime'];
79
+ exports.ACHIEVEMENT_CRITERIA_OPS = ['gte', 'lte', 'eq'];
80
+ exports.ACHIEVEMENT_CRITERIA_METRICS = ['count', 'lix'];
81
+ /**
82
+ * The only two documents a `datastore` criteria may read, and WHICH ONE IS THE
83
+ * TRUST DECISION: `mp:player:{userId}` is the room's flushed persistent
84
+ * playerVars (room-only writable ⇒ server-authoritative), `player:{userId}` is
85
+ * the player's own client-written save (forgeable by its owner, accepted
86
+ * deliberately — it is how a single-player world unlocks anything).
87
+ */
88
+ exports.DATA_STORE_CRITERIA_KEY_TEMPLATES = ['player:{userId}', 'mp:player:{userId}'];
89
+ /** A `datastore` criteria's `field`: a dot-path of letters, digits and underscores. */
90
+ exports.DATA_STORE_CRITERIA_FIELD_PATTERN = /^[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)*$/;
91
+ /** Backend caps (`ACHIEVEMENT_ICON_MAX_BYTES` / `ACHIEVEMENT_MESH_MAX_BYTES` defaults). */
92
+ exports.ACHIEVEMENT_ICON_MAX_BYTES = 8 * 1024 * 1024;
93
+ exports.ACHIEVEMENT_TROPHY_MAX_BYTES = 16 * 1024 * 1024;
94
+ /** Smallest square an icon can be and still read as a graphic on a plaque. */
95
+ exports.MIN_ICON_EDGE = 16;
96
+ /**
97
+ * Per-channel standard deviation below which the backend treats an image as one
98
+ * flat colour. Not zero — a real icon that has been through lossy encoding
99
+ * carries a little noise.
100
+ */
101
+ exports.MIN_ICON_STDDEV = 1;
102
+ const isAchievementKey = (value) => typeof value === 'string' && exports.ACHIEVEMENT_KEY_PATTERN.test(value);
103
+ exports.isAchievementKey = isAchievementKey;
104
+ // ---------------------------------------------------------------------------
105
+ // Icon + trophy file sniffing
106
+ // ---------------------------------------------------------------------------
107
+ // The backend sniffs the BYTES (magic numbers) rather than trusting the label,
108
+ // and accepts every raster format `sniffAssetKind` knows. The extension map here
109
+ // only picks the content-type for the multipart part.
110
+ const ICON_CONTENT_TYPES = {
111
+ '.png': 'image/png',
112
+ '.jpg': 'image/jpeg',
113
+ '.jpeg': 'image/jpeg',
114
+ '.webp': 'image/webp',
115
+ '.gif': 'image/gif',
116
+ '.avif': 'image/avif',
117
+ '.heic': 'image/heic',
118
+ '.heif': 'image/heif',
119
+ };
120
+ const lowerExtension = (file) => {
121
+ const base = file.slice(Math.max(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1);
122
+ const dot = base.lastIndexOf('.');
123
+ return dot <= 0 ? '' : base.slice(dot).toLowerCase();
124
+ };
125
+ /** Content type for the required `image` part — the 2D badge graphic. */
126
+ function iconContentTypeFromExtension(file) {
127
+ const contentType = ICON_CONTENT_TYPES[lowerExtension(file)];
128
+ if (!contentType) {
129
+ throw new Error(`unsupported achievement icon type "${lowerExtension(file) || file}" — use png, jpg/jpeg, webp, gif, avif or heic`);
130
+ }
131
+ return contentType;
132
+ }
133
+ /**
134
+ * What the backend's `assertValidAchievementIcon` checks, mirrored so a
135
+ * placeholder fails in a second instead of after an upload + a moderation pass.
136
+ * The two rejections are the two placeholders creators actually send: an image
137
+ * too small to read, and a single flat colour. Deliberately NOT a quality
138
+ * judgement — a two-tone glyph or a flat logo on a plate passes.
139
+ */
140
+ async function assertIconLooksReal(bytes, file) {
141
+ if (bytes.byteLength === 0)
142
+ throw new Error(`"${file}" is empty`);
143
+ const sharp = (await Promise.resolve().then(() => __importStar(require('sharp')))).default;
144
+ let meta;
145
+ let stats;
146
+ try {
147
+ const pipeline = sharp(Buffer.from(bytes));
148
+ meta = await pipeline.metadata();
149
+ stats = await pipeline.stats();
150
+ }
151
+ catch (err) {
152
+ throw new Error(`"${file}" could not be decoded as an image (${err instanceof Error ? err.message : String(err)}) — ` +
153
+ 'an achievement needs a real 2D graphic.');
154
+ }
155
+ const width = meta.width ?? 0;
156
+ const height = meta.height ?? 0;
157
+ if (width < exports.MIN_ICON_EDGE || height < exports.MIN_ICON_EDGE) {
158
+ throw new Error(`"${file}" is ${width || '?'}x${height || '?'}; an achievement icon must be at least ${exports.MIN_ICON_EDGE}x${exports.MIN_ICON_EDGE}. ` +
159
+ 'Placeholder images are rejected — upload the real artwork.');
160
+ }
161
+ // A fully transparent image is blank whatever its colour channels say, so an
162
+ // alpha-bearing icon is judged on its visible pixels: flatten onto mid grey
163
+ // (a colour no flat icon is likely to coincide with) and re-measure.
164
+ if (meta.hasAlpha) {
165
+ try {
166
+ const flattened = await sharp(Buffer.from(bytes))
167
+ .flatten({ background: { r: 128, g: 128, b: 128 } })
168
+ .png()
169
+ .toBuffer();
170
+ stats = await sharp(flattened).stats();
171
+ }
172
+ catch {
173
+ // Fall through to the un-flattened stats rather than fail on a flatten
174
+ // quirk — the flat-opaque case is still caught below.
175
+ }
176
+ }
177
+ const channels = (stats.channels ?? []).filter(
178
+ // A constant alpha channel means "every pixel opaque", which is normal, not
179
+ // evidence of blankness.
180
+ (_c, i) => !(meta.hasAlpha && i === (stats.channels?.length ?? 0) - 1));
181
+ const maxStdev = channels.reduce((acc, c) => Math.max(acc, c.stdev ?? 0), 0);
182
+ if (channels.length > 0 && maxStdev < exports.MIN_ICON_STDDEV) {
183
+ throw new Error(`"${file}" is a single flat colour with no visible graphic — upload the real 2D artwork for this achievement.`);
184
+ }
185
+ }
186
+ /** True when any criteria field was supplied — i.e. the caller means `criteria`. */
187
+ function hasCriteriaInput(input) {
188
+ if (!input)
189
+ return false;
190
+ return Object.values(input).some((v) => v !== undefined && v !== '');
191
+ }
192
+ const list = (values) => values.join(', ');
193
+ /**
194
+ * Validate + normalize the criteria the way the backend's `normalizeCriteria`
195
+ * does, and throw the same failures. Returns the exact object sent as the
196
+ * multipart `criteria` JSON string — no key the caller did not set.
197
+ */
198
+ function buildAchievementCriteria(input) {
199
+ const signal = input.signal;
200
+ if (!signal) {
201
+ throw new Error(`a criteria achievement needs --signal (one of ${list(exports.ACHIEVEMENT_CRITERIA_SIGNALS)})`);
202
+ }
203
+ if (!exports.ACHIEVEMENT_CRITERIA_SIGNALS.includes(signal)) {
204
+ throw new Error(`unknown --signal "${signal}" — supported signals: ${list(exports.ACHIEVEMENT_CRITERIA_SIGNALS)}`);
205
+ }
206
+ // The server requires `op`; it has no default of its own to override, and
207
+ // "reach N" is what nearly every badge means, so defaulting here is a
208
+ // convenience rather than a guess at server behaviour. It is echoed back in
209
+ // the register output so a `lte` badge that meant `gte` is visible.
210
+ const op = input.op ?? 'gte';
211
+ if (!exports.ACHIEVEMENT_CRITERIA_OPS.includes(op)) {
212
+ throw new Error(`unknown --op "${op}" — supported ops: ${list(exports.ACHIEVEMENT_CRITERIA_OPS)}`);
213
+ }
214
+ if (input.value === undefined)
215
+ throw new Error('a criteria achievement needs --value (the threshold to compare against)');
216
+ if (!Number.isFinite(input.value) || input.value < 0) {
217
+ throw new Error(`--value must be a number >= 0 (got ${input.value})`);
218
+ }
219
+ const criteria = {
220
+ signal: signal,
221
+ op: op,
222
+ value: input.value,
223
+ };
224
+ if (signal === 'analytics') {
225
+ if (!input.eventName) {
226
+ throw new Error('the "analytics" signal needs --event <platform analytics event> (e.g. world_entered) — ' +
227
+ 'a world cannot mint its own event name for criteria; the server rejects an unknown one by name.');
228
+ }
229
+ criteria.eventName = input.eventName;
230
+ }
231
+ else if (input.eventName) {
232
+ throw new Error(`--event only applies to the "analytics" signal (--signal is "${signal}")`);
233
+ }
234
+ if (signal === 'datastore') {
235
+ if (!input.key) {
236
+ throw new Error(`the "datastore" signal needs --criteria-key, one of the two per-user documents: ${exports.DATA_STORE_CRITERIA_KEY_TEMPLATES.map((t) => `"${t}"`).join(' or ')}`);
237
+ }
238
+ if (!exports.DATA_STORE_CRITERIA_KEY_TEMPLATES.includes(input.key)) {
239
+ throw new Error(`unknown --criteria-key "${input.key}" — it must be exactly ${exports.DATA_STORE_CRITERIA_KEY_TEMPLATES.map((t) => `"${t}"`).join(' or ')} ` +
240
+ '(a numeric sub-key is no longer writable by a session, so `field` selects the value).');
241
+ }
242
+ if (!input.field) {
243
+ throw new Error('the "datastore" signal needs --criteria-field: the dot-path to the number inside that document ' +
244
+ '(e.g. "stats.summits"; for mp:player:{userId} it names the persistent playerVar directly).');
245
+ }
246
+ if (!exports.DATA_STORE_CRITERIA_FIELD_PATTERN.test(input.field)) {
247
+ throw new Error(`--criteria-field "${input.field}" must be a dot-path of letters, digits and underscores (e.g. "stats.summits")`);
248
+ }
249
+ criteria.key = input.key;
250
+ criteria.field = input.field;
251
+ }
252
+ else {
253
+ if (input.key)
254
+ throw new Error(`--criteria-key only applies to the "datastore" signal (--signal is "${signal}")`);
255
+ if (input.field)
256
+ throw new Error(`--criteria-field only applies to the "datastore" signal (--signal is "${signal}")`);
257
+ }
258
+ if (signal === 'iwp') {
259
+ const metric = input.metric ?? 'count';
260
+ if (!exports.ACHIEVEMENT_CRITERIA_METRICS.includes(metric)) {
261
+ throw new Error(`unknown --metric "${metric}" — supported metrics: ${list(exports.ACHIEVEMENT_CRITERIA_METRICS)}`);
262
+ }
263
+ criteria.metric = metric;
264
+ }
265
+ else if (input.metric) {
266
+ throw new Error(`--metric only applies to the "iwp" signal (--signal is "${signal}")`);
267
+ }
268
+ return criteria;
269
+ }
270
+ /** One-line human summary of a stored criteria — the `list` column and the register echo. */
271
+ function formatAchievementCriteria(criteria) {
272
+ if (!criteria)
273
+ return '';
274
+ const cmp = `${criteria.op} ${criteria.value}`;
275
+ switch (criteria.signal) {
276
+ case 'datastore':
277
+ return `datastore ${criteria.key}.${criteria.field} ${cmp}`;
278
+ case 'iwp':
279
+ return `iwp ${criteria.metric ?? 'count'} ${cmp}`;
280
+ case 'analytics':
281
+ return `analytics ${criteria.eventName} ${cmp}`;
282
+ default:
283
+ return `${criteria.signal} ${cmp}`;
284
+ }
285
+ }
286
+ /**
287
+ * Resolve the trust marker. The backend's DTO defaults to `platform` because the
288
+ * ADMIN path (worldId omitted) is the one that needs it; for a WORLD
289
+ * registration `platform` is a mislabel — nothing in a world is first-party
290
+ * code. So this CLI always sends an explicit mode: `criteria` when a condition
291
+ * was declared, otherwise `room`, the only thing a world can actually award
292
+ * (the `awardAchievement` rule effect).
293
+ */
294
+ function resolveUnlockMode(explicit, hasCriteria) {
295
+ if (explicit !== undefined) {
296
+ if (!exports.ACHIEVEMENT_UNLOCK_MODES.includes(explicit)) {
297
+ throw new Error(`unknown --unlock-mode "${explicit}" — supported modes: ${list(exports.ACHIEVEMENT_UNLOCK_MODES)}`);
298
+ }
299
+ const mode = explicit;
300
+ if (mode === 'criteria' && !hasCriteria) {
301
+ throw new Error('--unlock-mode criteria needs the condition too — pass --signal/--value (and the signal\'s own flag).');
302
+ }
303
+ if (mode !== 'criteria' && hasCriteria) {
304
+ throw new Error(`criteria flags were given, but --unlock-mode is "${mode}" — the backend only reads a criteria when the mode is "criteria".`);
305
+ }
306
+ return mode;
307
+ }
308
+ return hasCriteria ? 'criteria' : 'room';
309
+ }
310
+ /**
311
+ * Build the multipart text fields, applying every local rule first. Keys the
312
+ * caller did not set are OMITTED rather than sent empty — an empty description
313
+ * and no description are the same row, and sending "" would overwrite nothing
314
+ * while looking like intent.
315
+ */
316
+ function buildAchievementRegistration(input) {
317
+ const warnings = [];
318
+ const key = input.key?.trim().toLowerCase() ?? '';
319
+ if (!key)
320
+ throw new Error('--key is required (the stable slug your rules and criteria name)');
321
+ if (!(0, exports.isAchievementKey)(key)) {
322
+ throw new Error(`--key "${key}" must be 2-80 chars of lowercase letters, digits, "_" or "-", starting alphanumeric. ` +
323
+ 'It is the identifier `awardAchievement` names, so treat it as a schema: renaming one needs a fresh registration.');
324
+ }
325
+ if (key !== input.key?.trim())
326
+ warnings.push(`key lowercased to "${key}" — the registry stores it lowercase.`);
327
+ const name = input.name?.trim() ?? '';
328
+ if (!name)
329
+ throw new Error('--name is required (the badge title players see)');
330
+ if (name.length > 100)
331
+ throw new Error(`--name is ${name.length} characters; the limit is 100`);
332
+ const description = input.description?.trim();
333
+ if (description !== undefined && description.length > 2000) {
334
+ throw new Error(`--description is ${description.length} characters; the limit is 2000`);
335
+ }
336
+ if (input.points !== undefined) {
337
+ if (!Number.isInteger(input.points) || input.points < 0 || input.points > 1000) {
338
+ throw new Error(`--points must be a whole number between 0 and 1000 (got ${input.points})`);
339
+ }
340
+ }
341
+ const hasCriteria = hasCriteriaInput(input.criteria);
342
+ const unlockMode = resolveUnlockMode(input.unlockMode, hasCriteria);
343
+ const criteria = hasCriteria ? buildAchievementCriteria(input.criteria) : undefined;
344
+ if (unlockMode === 'platform') {
345
+ warnings.push('unlockMode "platform" means FIRST-PARTY code awards it — nothing in your world can. ' +
346
+ 'Use "room" (an awardAchievement rule) or "criteria" (the backend measures it) unless you know why you want this.');
347
+ }
348
+ if (unlockMode === 'room') {
349
+ warnings.push(`register first, publish second: a rule awarding "${key}" is a silent no-op until this registration exists.`);
350
+ }
351
+ if (criteria?.key === 'player:{userId}') {
352
+ warnings.push('criteria on "player:{userId}" reads the PLAYER\'s own save — they can write it, so this badge is self-reported. ' +
353
+ 'Use "mp:player:{userId}" (the room\'s flushed persistent playerVars) for anything that must be trustworthy.');
354
+ }
355
+ return {
356
+ fields: {
357
+ key,
358
+ name,
359
+ ...(description ? { description } : {}),
360
+ ...(input.points !== undefined ? { points: input.points } : {}),
361
+ ...(input.hidden !== undefined ? { hidden: input.hidden } : {}),
362
+ unlockMode,
363
+ ...(criteria ? { criteria } : {}),
364
+ },
365
+ warnings,
366
+ };
367
+ }
368
+ /** Validate a PATCH body locally and refuse an empty one (a no-op round trip that reads as success). */
369
+ function buildAchievementUpdate(input) {
370
+ const patch = {};
371
+ if (input.name !== undefined) {
372
+ const name = input.name.trim();
373
+ if (!name)
374
+ throw new Error('--name cannot be empty');
375
+ if (name.length > 100)
376
+ throw new Error(`--name is ${name.length} characters; the limit is 100`);
377
+ patch.name = name;
378
+ }
379
+ if (input.description !== undefined) {
380
+ const description = input.description.trim();
381
+ if (description.length > 2000)
382
+ throw new Error(`--description is ${description.length} characters; the limit is 2000`);
383
+ patch.description = description;
384
+ }
385
+ if (input.points !== undefined) {
386
+ if (!Number.isInteger(input.points) || input.points < 0 || input.points > 1000) {
387
+ throw new Error(`--points must be a whole number between 0 and 1000 (got ${input.points})`);
388
+ }
389
+ patch.points = input.points;
390
+ }
391
+ if (input.hidden !== undefined)
392
+ patch.hidden = input.hidden;
393
+ if (input.active !== undefined)
394
+ patch.active = input.active;
395
+ if (Object.keys(patch).length === 0) {
396
+ throw new Error('nothing to update — pass at least one of --name, --description, --points, --hidden, --active');
397
+ }
398
+ return patch;
399
+ }
400
+ //# sourceMappingURL=achievement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"achievement.js","sourceRoot":"","sources":["../src/achievement.ts"],"names":[],"mappings":"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"}
package/dist/api.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare class HelixApi {
19
19
  request<T>(method: string, path: string, body?: unknown): Promise<T>;
20
20
  requestItem<T>(method: string, path: string, body?: unknown): Promise<T>;
21
21
  postMultipart<T>(path: string, form: FormData): Promise<T>;
22
+ sendMultipart<T>(method: string, path: string, form: FormData): Promise<T>;
22
23
  static forCredentials(creds: CliCredentials): HelixApi;
23
24
  }
24
25
  export declare function uploadToTicket(url: string, body: Buffer, contentType: string, cacheControl?: string): Promise<void>;
package/dist/api.js CHANGED
@@ -66,8 +66,13 @@ class HelixApi {
66
66
  // Blob (globals since Node 18, same undici that already backs `fetch` above),
67
67
  // so multipart needs no dependency.
68
68
  async postMultipart(path, form) {
69
+ return this.sendMultipart('POST', path, form);
70
+ }
71
+ // The same transport for the multipart endpoints that REPLACE rather than
72
+ // create (achievement icon/trophy are PUTs).
73
+ async sendMultipart(method, path, form) {
69
74
  const res = await fetch(`${this.baseUrl}${path}`, {
70
- method: 'POST',
75
+ method,
71
76
  headers: this.token ? { authorization: `Bearer ${this.token}` } : {},
72
77
  body: form,
73
78
  });
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}