@orakl/protocol 0.4.0 → 0.7.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.
@@ -1 +1 @@
1
- export type ErrorCode = "no_active_lobby" | "no_active_game" | "device_blocked" | "nickname_taken" | "device_in_lobby" | "player_not_found" | "player_not_pending" | "intermission_invalid_phase" | "not_in_intermission" | "category_name_exists" | "category_not_found" | "category_has_questions" | "user_not_found" | "curation_request_pending" | "curator_self_join" | "already_flagged" | "question_not_found" | "invalid_answer" | "game_in_progress" | "already_answered" | "observer_forbidden" | "no_questions" | "no_categories" | "too_few_players" | "hosting_closed" | "not_answered" | "flag_not_toggleable" | "solo_invalid_phase" | "solo_invalid_answer" | "solo_nonce_mismatch" | "solo_answer_expired" | "solo_guest_limit" | "solo_no_questions" | "solo_resume_denied" | "solo_auth_failed";
1
+ export type ErrorCode = "no_active_lobby" | "no_active_game" | "device_blocked" | "nickname_taken" | "device_in_lobby" | "player_not_found" | "player_not_pending" | "intermission_invalid_phase" | "not_in_intermission" | "category_name_exists" | "category_not_found" | "category_has_questions" | "tag_name_exists" | "tag_not_found" | "tag_has_questions" | "tag_in_season" | "category_in_season" | "season_name_exists" | "season_not_found" | "user_not_found" | "curation_request_pending" | "curator_self_join" | "already_flagged" | "question_not_found" | "invalid_answer" | "game_in_progress" | "already_answered" | "observer_forbidden" | "no_questions" | "season_out_of_season" | "no_categories" | "too_few_players" | "hosting_closed" | "not_answered" | "flag_not_toggleable" | "solo_invalid_phase" | "solo_invalid_answer" | "solo_nonce_mismatch" | "solo_answer_expired" | "solo_guest_limit" | "solo_no_questions" | "solo_season_out_of_season" | "solo_resume_denied" | "solo_auth_failed";
@@ -125,6 +125,45 @@ declare const CategorySchema: Schema.Struct<{
125
125
  question_count: typeof Schema.Number;
126
126
  }>;
127
127
  export type Category = typeof CategorySchema.Type;
128
+ declare const TagSchema: Schema.Struct<{
129
+ id: typeof Schema.String;
130
+ name: typeof Schema.String;
131
+ /** Questions whose `metadata.tags` carries this name. */
132
+ question_count: typeof Schema.Number;
133
+ }>;
134
+ export type Tag = typeof TagSchema.Type;
135
+ declare const SeasonSchema: Schema.Struct<{
136
+ id: typeof Schema.String;
137
+ name: typeof Schema.String;
138
+ description: Schema.NullOr<typeof Schema.String>;
139
+ icon: Schema.NullOr<typeof Schema.String>;
140
+ color: Schema.NullOr<typeof Schema.String>;
141
+ /** `window_start`/`window_end` are `MM-DD` when true, `YYYY-MM-DD` when false. */
142
+ repeats_yearly: typeof Schema.Boolean;
143
+ window_start: typeof Schema.String;
144
+ window_end: typeof Schema.String;
145
+ /** Member `categories.id` values. */
146
+ category_ids: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
147
+ /** Member tag names. */
148
+ tag_names: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
149
+ /** Distinct questions reachable through the member categories and tags. */
150
+ pool_size: typeof Schema.Number;
151
+ }>;
152
+ export type Season = typeof SeasonSchema.Type;
153
+ /** A Season as the play pickers offer it: selectable in its window, locked with its opening day outside. */
154
+ export declare const SeasonOptionSchema: Schema.Struct<{
155
+ id: typeof Schema.String;
156
+ name: typeof Schema.String;
157
+ icon: Schema.NullOr<typeof Schema.String>;
158
+ color: Schema.NullOr<typeof Schema.String>;
159
+ /** Distinct questions reachable through the Season's categories and Tags. */
160
+ count: typeof Schema.Number;
161
+ /** True outside the window; a locked Season cannot be picked. */
162
+ locked: typeof Schema.Boolean;
163
+ /** Next day the window opens (`YYYY-MM-DD`), only while locked. */
164
+ opensOn: Schema.NullOr<typeof Schema.String>;
165
+ }>;
166
+ export type SeasonOption = typeof SeasonOptionSchema.Type;
128
167
  /** Body of `GET /api/pages/manage/categories`. */
129
168
  export declare const ManageCategoriesPageSchema: Schema.Struct<{
130
169
  initial: Schema.mutable<Schema.Array$<Schema.Schema<{
@@ -142,6 +181,40 @@ export declare const ManageCategoriesPageSchema: Schema.Struct<{
142
181
  readonly icon: string | null;
143
182
  readonly question_count: number;
144
183
  }, never>>>;
184
+ tags: Schema.mutable<Schema.Array$<Schema.Schema<{
185
+ readonly name: string;
186
+ readonly id: string;
187
+ readonly question_count: number;
188
+ }, {
189
+ readonly name: string;
190
+ readonly id: string;
191
+ readonly question_count: number;
192
+ }, never>>>;
193
+ seasons: Schema.mutable<Schema.Array$<Schema.Schema<{
194
+ readonly name: string;
195
+ readonly id: string;
196
+ readonly color: string | null;
197
+ readonly description: string | null;
198
+ readonly icon: string | null;
199
+ readonly repeats_yearly: boolean;
200
+ readonly window_start: string;
201
+ readonly window_end: string;
202
+ readonly category_ids: string[];
203
+ readonly tag_names: string[];
204
+ readonly pool_size: number;
205
+ }, {
206
+ readonly name: string;
207
+ readonly id: string;
208
+ readonly color: string | null;
209
+ readonly description: string | null;
210
+ readonly icon: string | null;
211
+ readonly repeats_yearly: boolean;
212
+ readonly window_start: string;
213
+ readonly window_end: string;
214
+ readonly category_ids: string[];
215
+ readonly tag_names: string[];
216
+ readonly pool_size: number;
217
+ }, never>>>;
145
218
  }>;
146
219
  declare const AdminFlagRowSchema: Schema.Struct<{
147
220
  questionId: typeof Schema.String;
@@ -307,6 +380,7 @@ declare const QuizPresetSchema: Schema.Struct<{
307
380
  name: typeof Schema.String;
308
381
  description: Schema.NullOr<typeof Schema.String>;
309
382
  category_ids: typeof Schema.String;
383
+ season_ids: typeof Schema.String;
310
384
  timer_duration: typeof Schema.Number;
311
385
  questions_per_round: typeof Schema.Number;
312
386
  difficulty: typeof Schema.String;
@@ -317,8 +391,41 @@ declare const QuizPresetSchema: Schema.Struct<{
317
391
  created_at: typeof Schema.String;
318
392
  }>;
319
393
  export type QuizPreset = typeof QuizPresetSchema.Type;
394
+ /** What stopped a saved Quiz's members from drawing: closed or gone Seasons, gone or hidden categories. */
395
+ declare const PresetMarksSchema: Schema.Struct<{
396
+ closedSeasons: Schema.mutable<Schema.Array$<Schema.Schema<{
397
+ readonly name: string;
398
+ readonly id: string;
399
+ readonly opensOn: string | null;
400
+ }, {
401
+ readonly name: string;
402
+ readonly id: string;
403
+ readonly opensOn: string | null;
404
+ }, never>>>;
405
+ missingSeasons: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
406
+ missingCategories: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
407
+ hiddenCategories: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
408
+ }>;
409
+ export type PresetMarks = typeof PresetMarksSchema.Type;
320
410
  /** Body of `GET /api/pages/curator/create`. */
321
411
  export declare const CuratorCreatePageSchema: Schema.Struct<{
412
+ seasons: Schema.mutable<Schema.Array$<Schema.Schema<{
413
+ readonly name: string;
414
+ readonly count: number;
415
+ readonly id: string;
416
+ readonly color: string | null;
417
+ readonly icon: string | null;
418
+ readonly locked: boolean;
419
+ readonly opensOn: string | null;
420
+ }, {
421
+ readonly name: string;
422
+ readonly count: number;
423
+ readonly id: string;
424
+ readonly color: string | null;
425
+ readonly icon: string | null;
426
+ readonly locked: boolean;
427
+ readonly opensOn: string | null;
428
+ }, never>>>;
322
429
  categories: Schema.mutable<Schema.Array$<Schema.Schema<{
323
430
  readonly name: string;
324
431
  readonly count: number;
@@ -339,8 +446,9 @@ export declare const CuratorCreatePageSchema: Schema.Struct<{
339
446
  readonly description: string | null;
340
447
  readonly difficulty: string;
341
448
  readonly created_at: string;
342
- readonly curator_id: string;
343
449
  readonly category_ids: string;
450
+ readonly curator_id: string;
451
+ readonly season_ids: string;
344
452
  readonly timer_duration: number;
345
453
  readonly questions_per_round: number;
346
454
  readonly advance_mode: string;
@@ -353,8 +461,9 @@ export declare const CuratorCreatePageSchema: Schema.Struct<{
353
461
  readonly description: string | null;
354
462
  readonly difficulty: string;
355
463
  readonly created_at: string;
356
- readonly curator_id: string;
357
464
  readonly category_ids: string;
465
+ readonly curator_id: string;
466
+ readonly season_ids: string;
358
467
  readonly timer_duration: number;
359
468
  readonly questions_per_round: number;
360
469
  readonly advance_mode: string;
@@ -362,6 +471,20 @@ export declare const CuratorCreatePageSchema: Schema.Struct<{
362
471
  readonly access_mode: string;
363
472
  readonly max_players: number | null;
364
473
  }, never>>>;
474
+ presetMarks: Schema.Record$<typeof Schema.String, Schema.Struct<{
475
+ closedSeasons: Schema.mutable<Schema.Array$<Schema.Schema<{
476
+ readonly name: string;
477
+ readonly id: string;
478
+ readonly opensOn: string | null;
479
+ }, {
480
+ readonly name: string;
481
+ readonly id: string;
482
+ readonly opensOn: string | null;
483
+ }, never>>>;
484
+ missingSeasons: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
485
+ missingCategories: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
486
+ hiddenCategories: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
487
+ }>>;
365
488
  presetLimit: typeof Schema.Number;
366
489
  subscription: Schema.NullOr<Schema.Struct<{
367
490
  user_id: typeof Schema.String;
@@ -389,6 +512,7 @@ export declare const CuratorHistoryPageSchema: Schema.Struct<{
389
512
  readonly started_at: string;
390
513
  readonly player_count: number;
391
514
  readonly total_questions: number;
515
+ readonly seasonNames: string[];
392
516
  readonly winners: string[];
393
517
  readonly top_score: number | null;
394
518
  }, {
@@ -397,6 +521,7 @@ export declare const CuratorHistoryPageSchema: Schema.Struct<{
397
521
  readonly started_at: string;
398
522
  readonly player_count: number;
399
523
  readonly total_questions: number;
524
+ readonly seasonNames: string[];
400
525
  readonly winners: string[];
401
526
  readonly top_score: number | null;
402
527
  }, never>>>;
@@ -419,6 +544,8 @@ export declare const CuratorHistoryEntryPageSchema: Schema.Struct<{
419
544
  started_at: typeof Schema.String;
420
545
  ended_at: Schema.NullOr<typeof Schema.String>;
421
546
  categoryIds: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
547
+ seasonIds: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
548
+ seasonNames: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
422
549
  timer_duration: typeof Schema.Number;
423
550
  total_questions: typeof Schema.Number;
424
551
  player_count: typeof Schema.Number;
@@ -530,6 +657,8 @@ export declare const CuratorQuestionsPageSchema: Schema.Struct<{
530
657
  } | undefined;
531
658
  }, never>>>;
532
659
  questionsCursor: Schema.NullOr<typeof Schema.String>;
660
+ /** Admin-defined tag names, sorted. */
661
+ tags: Schema.mutable<Schema.Array$<Schema.Schema<string, string, never>>>;
533
662
  }>;
534
663
  /** Body of `GET /api/pages/solo/layout`. */
535
664
  export declare const SoloLayoutPageSchema: Schema.Struct<{
@@ -539,6 +668,7 @@ export declare const SoloLayoutPageSchema: Schema.Struct<{
539
668
  nickname: typeof Schema.String;
540
669
  profileAvatarSrc: typeof Schema.String;
541
670
  categoryDataJson: typeof Schema.String;
671
+ seasonDataJson: typeof Schema.String;
542
672
  }>;
543
673
  declare const LeaderboardEntrySchema: Schema.Struct<{
544
674
  rank: typeof Schema.Number;
@@ -576,8 +706,10 @@ export declare const SoloLeaderboardPageSchema: Schema.Struct<{
576
706
  readonly completed_at: number;
577
707
  }, never>>>;
578
708
  board: Schema.Literal<["score", "streak", "accuracy", "speed", "survival"]>;
579
- scope: Schema.Literal<["all-time", "daily", "weekly", "monthly"]>;
709
+ scope: Schema.Literal<["all-time", "daily", "weekly", "monthly", "season"]>;
580
710
  categoryId: Schema.NullOr<typeof Schema.String>;
711
+ seasonId: Schema.NullOr<typeof Schema.String>;
712
+ opening: Schema.NullOr<typeof Schema.String>;
581
713
  difficulty: Schema.NullOr<Schema.Literal<["easy", "medium", "hard"]>>;
582
714
  categories: Schema.mutable<Schema.Array$<Schema.Schema<{
583
715
  readonly name: string;
@@ -586,6 +718,19 @@ export declare const SoloLeaderboardPageSchema: Schema.Struct<{
586
718
  readonly name: string;
587
719
  readonly id: string;
588
720
  }, never>>>;
721
+ seasonBoards: Schema.mutable<Schema.Array$<Schema.Schema<{
722
+ readonly name: string;
723
+ readonly label: string;
724
+ readonly current: boolean;
725
+ readonly seasonId: string;
726
+ readonly opening: string;
727
+ }, {
728
+ readonly name: string;
729
+ readonly label: string;
730
+ readonly current: boolean;
731
+ readonly seasonId: string;
732
+ readonly opening: string;
733
+ }, never>>>;
589
734
  userRank: Schema.NullOr<typeof Schema.Number>;
590
735
  eligibleCount: typeof Schema.Number;
591
736
  percentile: Schema.NullOr<typeof Schema.Number>;
@@ -119,9 +119,47 @@ const CategorySchema = Schema.Struct({
119
119
  color: Schema.NullOr(Schema.String),
120
120
  question_count: Schema.Number,
121
121
  });
122
+ const TagSchema = Schema.Struct({
123
+ id: Schema.String,
124
+ name: Schema.String,
125
+ /** Questions whose `metadata.tags` carries this name. */
126
+ question_count: Schema.Number,
127
+ });
128
+ const SeasonSchema = Schema.Struct({
129
+ id: Schema.String,
130
+ name: Schema.String,
131
+ description: Schema.NullOr(Schema.String),
132
+ icon: Schema.NullOr(Schema.String),
133
+ color: Schema.NullOr(Schema.String),
134
+ /** `window_start`/`window_end` are `MM-DD` when true, `YYYY-MM-DD` when false. */
135
+ repeats_yearly: Schema.Boolean,
136
+ window_start: Schema.String,
137
+ window_end: Schema.String,
138
+ /** Member `categories.id` values. */
139
+ category_ids: Arr(Schema.String),
140
+ /** Member tag names. */
141
+ tag_names: Arr(Schema.String),
142
+ /** Distinct questions reachable through the member categories and tags. */
143
+ pool_size: Schema.Number,
144
+ });
145
+ /** A Season as the play pickers offer it: selectable in its window, locked with its opening day outside. */
146
+ export const SeasonOptionSchema = Schema.Struct({
147
+ id: Schema.String,
148
+ name: Schema.String,
149
+ icon: Schema.NullOr(Schema.String),
150
+ color: Schema.NullOr(Schema.String),
151
+ /** Distinct questions reachable through the Season's categories and Tags. */
152
+ count: Schema.Number,
153
+ /** True outside the window; a locked Season cannot be picked. */
154
+ locked: Schema.Boolean,
155
+ /** Next day the window opens (`YYYY-MM-DD`), only while locked. */
156
+ opensOn: Schema.NullOr(Schema.String),
157
+ });
122
158
  /** Body of `GET /api/pages/manage/categories`. */
123
159
  export const ManageCategoriesPageSchema = Schema.Struct({
124
160
  initial: Arr(CategorySchema),
161
+ tags: Arr(TagSchema),
162
+ seasons: Arr(SeasonSchema),
125
163
  });
126
164
  const AdminFlagRowSchema = Schema.Struct({
127
165
  questionId: Schema.String,
@@ -210,6 +248,7 @@ const QuizPresetSchema = Schema.Struct({
210
248
  name: Schema.String,
211
249
  description: Schema.NullOr(Schema.String),
212
250
  category_ids: Schema.String,
251
+ season_ids: Schema.String,
213
252
  timer_duration: Schema.Number,
214
253
  questions_per_round: Schema.Number,
215
254
  difficulty: Schema.String,
@@ -219,11 +258,24 @@ const QuizPresetSchema = Schema.Struct({
219
258
  max_players: Schema.NullOr(Schema.Number),
220
259
  created_at: Schema.String,
221
260
  });
261
+ /** What stopped a saved Quiz's members from drawing: closed or gone Seasons, gone or hidden categories. */
262
+ const PresetMarksSchema = Schema.Struct({
263
+ closedSeasons: Arr(Schema.Struct({
264
+ id: Schema.String,
265
+ name: Schema.String,
266
+ opensOn: Schema.NullOr(Schema.String),
267
+ })),
268
+ missingSeasons: Arr(Schema.String),
269
+ missingCategories: Arr(Schema.String),
270
+ hiddenCategories: Arr(Schema.String),
271
+ });
222
272
  /** Body of `GET /api/pages/curator/create`. */
223
273
  export const CuratorCreatePageSchema = Schema.Struct({
274
+ seasons: Arr(SeasonOptionSchema),
224
275
  categories: Arr(CategoryOptionSchema),
225
276
  categoryColors: Schema.Record({ key: Schema.String, value: Schema.String }),
226
277
  presets: Arr(QuizPresetSchema),
278
+ presetMarks: Schema.Record({ key: Schema.String, value: PresetMarksSchema }),
227
279
  presetLimit: Schema.Number,
228
280
  subscription: Schema.NullOr(SubscriptionRowSchema),
229
281
  allowance: HostingAllowanceSchema,
@@ -234,6 +286,7 @@ const GameHistoryListItemSchema = Schema.Struct({
234
286
  started_at: Schema.String,
235
287
  player_count: Schema.Number,
236
288
  total_questions: Schema.Number,
289
+ seasonNames: Arr(Schema.String),
237
290
  winners: Arr(Schema.String),
238
291
  top_score: Schema.NullOr(Schema.Number),
239
292
  });
@@ -248,6 +301,8 @@ const GameHistoryEntrySchema = Schema.Struct({
248
301
  started_at: Schema.String,
249
302
  ended_at: Schema.NullOr(Schema.String),
250
303
  categoryIds: Arr(Schema.String),
304
+ seasonIds: Arr(Schema.String),
305
+ seasonNames: Arr(Schema.String),
251
306
  timer_duration: Schema.Number,
252
307
  total_questions: Schema.Number,
253
308
  player_count: Schema.Number,
@@ -324,6 +379,8 @@ export const CuratorQuestionsPageSchema = Schema.Struct({
324
379
  categories: Arr(CuratorQuestionsCategoryOptionSchema),
325
380
  ownQuestions: Arr(OwnQuestionSchema),
326
381
  questionsCursor: Schema.NullOr(Schema.String),
382
+ /** Admin-defined tag names, sorted. */
383
+ tags: Arr(Schema.String),
327
384
  });
328
385
  /** Body of `GET /api/pages/solo/layout`. */
329
386
  export const SoloLayoutPageSchema = Schema.Struct({
@@ -333,6 +390,7 @@ export const SoloLayoutPageSchema = Schema.Struct({
333
390
  nickname: Schema.String,
334
391
  profileAvatarSrc: Schema.String,
335
392
  categoryDataJson: Schema.String,
393
+ seasonDataJson: Schema.String,
336
394
  });
337
395
  const LeaderboardEntrySchema = Schema.Struct({
338
396
  rank: Schema.Number,
@@ -349,10 +407,19 @@ const LeaderboardEntrySchema = Schema.Struct({
349
407
  export const SoloLeaderboardPageSchema = Schema.Struct({
350
408
  entries: Arr(LeaderboardEntrySchema),
351
409
  board: Schema.Literal("score", "streak", "accuracy", "speed", "survival"),
352
- scope: Schema.Literal("all-time", "daily", "weekly", "monthly"),
410
+ scope: Schema.Literal("all-time", "daily", "weekly", "monthly", "season"),
353
411
  categoryId: Schema.NullOr(Schema.String),
412
+ seasonId: Schema.NullOr(Schema.String),
413
+ opening: Schema.NullOr(Schema.String),
354
414
  difficulty: Schema.NullOr(Schema.Literal("easy", "medium", "hard")),
355
415
  categories: Arr(Schema.Struct({ id: Schema.String, name: Schema.String })),
416
+ seasonBoards: Arr(Schema.Struct({
417
+ seasonId: Schema.String,
418
+ name: Schema.String,
419
+ opening: Schema.String,
420
+ label: Schema.String,
421
+ current: Schema.Boolean,
422
+ })),
356
423
  userRank: Schema.NullOr(Schema.Number),
357
424
  eligibleCount: Schema.Number,
358
425
  percentile: Schema.NullOr(Schema.Number),
@@ -72,6 +72,7 @@ declare const SoloHistoryEntrySchema: Schema.Struct<{
72
72
  mode: typeof Schema.String;
73
73
  difficulty: typeof Schema.String;
74
74
  category_ids: typeof Schema.String;
75
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
75
76
  completed_at: typeof Schema.Number;
76
77
  }>;
77
78
  export type SoloHistoryEntry = typeof SoloHistoryEntrySchema.Type;
@@ -89,6 +90,7 @@ declare const PlayerGamePlacementSchema: Schema.Struct<{
89
90
  final_score: typeof Schema.Number;
90
91
  rank: typeof Schema.Number;
91
92
  player_count: typeof Schema.Number;
93
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
92
94
  badges: Schema.mutable<Schema.Array$<Schema.Literal<["victor", "flawless", "sharpshooter", "podium", "unstoppable", "on-a-roll", "survivor", "giant-slayer", "pantheon", "specialist", "polymath", "phoenix", "strong-finish", "master-of-none", "faster-than-most", "clutch", "quick-draw", "decisive", "sure-handed", "unbroken-focus", "devotee", "herculean", "undaunted", "measured", "strong-start", "new-heights", "far-horizons", "cassandra", "lone-torch", "ascendant", "undisputed"]>>>;
93
95
  }>;
94
96
  export type PlayerGamePlacement = typeof PlayerGamePlacementSchema.Type;
@@ -105,6 +107,7 @@ export declare const HistoryPageSchema: Schema.Struct<{
105
107
  mode: typeof Schema.String;
106
108
  difficulty: typeof Schema.String;
107
109
  category_ids: typeof Schema.String;
110
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
108
111
  completed_at: typeof Schema.Number;
109
112
  }>>>;
110
113
  trendRuns: Schema.mutable<Schema.Array$<Schema.Struct<{
@@ -117,6 +120,7 @@ export declare const HistoryPageSchema: Schema.Struct<{
117
120
  mode: typeof Schema.String;
118
121
  difficulty: typeof Schema.String;
119
122
  category_ids: typeof Schema.String;
123
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
120
124
  completed_at: typeof Schema.Number;
121
125
  }>>>;
122
126
  latestRunAt: Schema.NullOr<typeof Schema.Number>;
@@ -164,6 +168,7 @@ export declare const HistoryPageSchema: Schema.Struct<{
164
168
  final_score: typeof Schema.Number;
165
169
  rank: typeof Schema.Number;
166
170
  player_count: typeof Schema.Number;
171
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
167
172
  badges: Schema.mutable<Schema.Array$<Schema.Literal<["victor", "flawless", "sharpshooter", "podium", "unstoppable", "on-a-roll", "survivor", "giant-slayer", "pantheon", "specialist", "polymath", "phoenix", "strong-finish", "master-of-none", "faster-than-most", "clutch", "quick-draw", "decisive", "sure-handed", "unbroken-focus", "devotee", "herculean", "undaunted", "measured", "strong-start", "new-heights", "far-horizons", "cassandra", "lone-torch", "ascendant", "undisputed"]>>>;
168
173
  }>>>;
169
174
  runsNextCursor: Schema.NullOr<typeof Schema.String>;
@@ -178,6 +183,7 @@ export declare const GameReviewPageSchema: Schema.Struct<{
178
183
  finalScore: typeof Schema.Number;
179
184
  rank: typeof Schema.Number;
180
185
  playerCount: typeof Schema.Number;
186
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
181
187
  }>;
182
188
  standings: Schema.mutable<Schema.Array$<Schema.Struct<{
183
189
  id: typeof Schema.String;
@@ -238,6 +244,7 @@ export declare const SoloReviewPageSchema: Schema.Struct<{
238
244
  difficulty: typeof Schema.String;
239
245
  completedAt: typeof Schema.Number;
240
246
  categories: Schema.mutable<Schema.Array$<typeof Schema.String>>;
247
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
241
248
  }>;
242
249
  badges: Schema.mutable<Schema.Array$<Schema.Struct<{
243
250
  id: Schema.Literal<["victor", "flawless", "sharpshooter", "podium", "unstoppable", "on-a-roll", "survivor", "giant-slayer", "pantheon", "specialist", "polymath", "phoenix", "strong-finish", "master-of-none", "faster-than-most", "clutch", "quick-draw", "decisive", "sure-handed", "unbroken-focus", "devotee", "herculean", "undaunted", "measured", "strong-start", "new-heights", "far-horizons", "cassandra", "lone-torch", "ascendant", "undisputed"]>;
@@ -75,6 +75,7 @@ const SoloHistoryEntrySchema = Schema.Struct({
75
75
  mode: Schema.String,
76
76
  difficulty: Schema.String,
77
77
  category_ids: Schema.String,
78
+ seasons: Schema.mutable(Schema.Array(Schema.String)),
78
79
  completed_at: Schema.Number,
79
80
  });
80
81
  const SoloStatsSchema = Schema.Struct({
@@ -107,6 +108,7 @@ const PlayerGamePlacementSchema = Schema.Struct({
107
108
  final_score: Schema.Number,
108
109
  rank: Schema.Number,
109
110
  player_count: Schema.Number,
111
+ seasons: Schema.mutable(Schema.Array(Schema.String)),
110
112
  badges: Schema.mutable(Schema.Array(BadgeIdSchema)),
111
113
  });
112
114
  /** Body of `GET /api/pages/history`. */
@@ -150,6 +152,7 @@ export const GameReviewPageSchema = Schema.Struct({
150
152
  finalScore: Schema.Number,
151
153
  rank: Schema.Number,
152
154
  playerCount: Schema.Number,
155
+ seasons: Schema.mutable(Schema.Array(Schema.String)),
153
156
  }),
154
157
  standings: Schema.mutable(Schema.Array(GameStandingEntrySchema)),
155
158
  badges: Schema.mutable(Schema.Array(Schema.Struct({ id: BadgeIdSchema, rarity: RaritySchema }))),
@@ -193,6 +196,7 @@ export const SoloReviewPageSchema = Schema.Struct({
193
196
  difficulty: Schema.String,
194
197
  completedAt: Schema.Number,
195
198
  categories: Schema.mutable(Schema.Array(Schema.String)),
199
+ seasons: Schema.mutable(Schema.Array(Schema.String)),
196
200
  }),
197
201
  badges: Schema.mutable(Schema.Array(Schema.Struct({ id: BadgeIdSchema, rarity: RaritySchema }))),
198
202
  categoryStats: Schema.mutable(Schema.Array(Schema.Struct({
@@ -96,6 +96,7 @@ export declare const QuizContextPageSchema: Schema.Struct<{
96
96
  quizName: typeof Schema.String;
97
97
  description: typeof Schema.String;
98
98
  categories: Schema.mutable<Schema.Array$<typeof Schema.String>>;
99
+ seasons: Schema.mutable<Schema.Array$<typeof Schema.String>>;
99
100
  difficulty: Schema.NullOr<Schema.Literal<["all", "easy", "medium", "hard"]>>;
100
101
  accessMode: Schema.Literal<["open", "invite-only"]>;
101
102
  maxPlayers: Schema.NullOr<typeof Schema.Number>;
@@ -85,6 +85,7 @@ const LobbySchema = Schema.Struct({
85
85
  quizName: Schema.String,
86
86
  description: Schema.String,
87
87
  categories: Schema.mutable(Schema.Array(Schema.String)),
88
+ seasons: Schema.mutable(Schema.Array(Schema.String)),
88
89
  difficulty: Schema.NullOr(DifficultyFilterSchema),
89
90
  accessMode: AccessModeSchema,
90
91
  maxPlayers: Schema.NullOr(Schema.Number),
package/dist/solo-ws.d.ts CHANGED
@@ -10,6 +10,8 @@ export type SoloAuthMessage = {
10
10
  export type SoloStartMessage = {
11
11
  type: "solo:start";
12
12
  categoryIds: string[];
13
+ /** Seasons drawn from beside the categories. */
14
+ seasonIds?: string[];
13
15
  timerDuration: number;
14
16
  questionCount: number;
15
17
  mode: "normal" | "endless";
@@ -200,7 +202,7 @@ export type SoloPingMessage = {
200
202
  };
201
203
  export type SoloErrorMessage = {
202
204
  type: "solo:error";
203
- code: "auth_failed" | "entitlement_exceeded" | "invalid_message" | "session_expired" | "internal";
205
+ code: "auth_failed" | "entitlement_exceeded" | "invalid_message" | "session_expired" | "season_out_of_season" | "no_questions" | "internal";
204
206
  message: string;
205
207
  };
206
208
  /** Build a `solo:error` frame — the one shape every failure site sends. */
@@ -1,6 +1,6 @@
1
1
  /** Which ranking a leaderboard sorts by. */
2
2
  export type LeaderboardBoard = "score" | "streak" | "accuracy" | "speed" | "survival";
3
- /** Rolling window a leaderboard is scoped to. */
4
- export type LeaderboardScope = "all-time" | "daily" | "weekly" | "monthly";
3
+ /** Rolling window a leaderboard is scoped to, or one Season opening. */
4
+ export type LeaderboardScope = "all-time" | "daily" | "weekly" | "monthly" | "season";
5
5
  /** Difficulty filter a leaderboard is narrowed to. */
6
6
  export type LeaderboardDifficulty = "easy" | "medium" | "hard";
@@ -23,6 +23,7 @@ export declare const ClientMessageSchema: Schema.Union<[Schema.Struct<{
23
23
  }>, Schema.Struct<{
24
24
  type: Schema.Literal<["curator:start"]>;
25
25
  categoryIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.NonEmptyString>>>;
26
+ seasonIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.NonEmptyString>>>;
26
27
  timerDuration: Schema.optional<Schema.Literal<[15, 30, 45, 60]>>;
27
28
  questionsPerRound: Schema.optional<Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>>;
28
29
  difficulty: Schema.optional<Schema.Literal<["all", "easy", "medium", "hard"]>>;
@@ -94,6 +94,7 @@ const CuratorStartMessageSchema = Schema.Struct({
94
94
  // preloadedQuestions carries the round — game-ws-server.ts's makeStartGame
95
95
  // surfaces the friendly "select a category" error itself.
96
96
  categoryIds: Schema.optional(Schema.Array(Schema.NonEmptyString).pipe(Schema.maxItems(50))),
97
+ seasonIds: Schema.optional(Schema.Array(Schema.NonEmptyString).pipe(Schema.maxItems(50))),
97
98
  timerDuration: Schema.optional(Schema.Literal(...GAME.roundConfig.timerOptions)),
98
99
  // Not the QuestionsPerRound literal on purpose (ws.ts types this as a plain
99
100
  // number) — bounded generously instead, mirroring DrawQuestionsSchema's cap.
@@ -5,6 +5,7 @@ export declare const SoloClientMessageSchema: Schema.Union<[Schema.Struct<{
5
5
  }>, Schema.Struct<{
6
6
  type: Schema.Literal<["solo:start"]>;
7
7
  categoryIds: Schema.filter<Schema.Array$<typeof Schema.NonEmptyString>>;
8
+ seasonIds: Schema.optional<Schema.filter<Schema.Array$<typeof Schema.NonEmptyString>>>;
8
9
  timerDuration: Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>;
9
10
  questionCount: Schema.filter<Schema.filter<Schema.filter<typeof Schema.Number>>>;
10
11
  mode: Schema.Literal<["normal", "endless"]>;
@@ -17,6 +17,7 @@ const SoloAuthMessageSchema = Schema.Struct({
17
17
  const SoloStartMessageSchema = Schema.Struct({
18
18
  type: Schema.Literal("solo:start"),
19
19
  categoryIds: Schema.Array(Schema.NonEmptyString).pipe(Schema.maxItems(50)),
20
+ seasonIds: Schema.optional(Schema.Array(Schema.NonEmptyString).pipe(Schema.maxItems(50))),
20
21
  // Plain `number` on the hand-written type (clamped to [5,120] downstream) —
21
22
  // bounded generously here against absurd/non-finite values.
22
23
  timerDuration: Schema.Number.pipe(Schema.finite(), Schema.greaterThan(0), Schema.lessThanOrEqualTo(600)),
package/dist/ws.d.ts CHANGED
@@ -49,6 +49,9 @@ export interface PlayerRateMessage {
49
49
  export interface CuratorStartMessage {
50
50
  type: "curator:start";
51
51
  categoryIds?: string[];
52
+ /** Season ids; the server keeps only those the Lobby fixed at create or
53
+ * re-host. */
54
+ seasonIds?: string[];
52
55
  timerDuration?: TimerDuration;
53
56
  questionsPerRound?: number;
54
57
  difficulty?: DifficultyFilter;
@@ -108,6 +111,8 @@ export interface LobbyUpdateMessage {
108
111
  description?: string;
109
112
  /** Curator's live-edited category list. */
110
113
  categories?: readonly string[];
114
+ /** Names of the Seasons the Lobby draws from. */
115
+ seasons?: readonly string[];
111
116
  /** Curator's live-edited difficulty filter. */
112
117
  difficulty?: DifficultyFilter;
113
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orakl/protocol",
3
- "version": "0.4.0",
3
+ "version": "0.7.0",
4
4
  "description": "Orakl wire contract: WebSocket frames and API response schemas.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {