@orakl/protocol 0.11.0 → 0.13.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/dist/emotes.d.ts +72 -4
- package/dist/emotes.js +45 -62
- package/dist/error-codes.d.ts +1 -1
- package/dist/game.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pages/app.schema.d.ts +3 -6
- package/dist/pages/app.schema.js +5 -2
- package/dist/pages/common.schema.d.ts +11 -6
- package/dist/pages/common.schema.js +2 -2
- package/dist/pages/history.schema.d.ts +22 -12
- package/dist/pages/history.schema.js +3 -2
- package/dist/pages/quiz.schema.d.ts +28 -6
- package/dist/pages/quiz.schema.js +6 -0
- package/dist/question.schema.d.ts +16 -0
- package/dist/question.schema.js +11 -0
- package/dist/ws-game.schema.d.ts +1 -1
- package/dist/ws-game.schema.js +3 -2
- package/package.json +1 -1
package/dist/emotes.d.ts
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Most emotes a Player's set holds. */
|
|
3
|
+
export declare const MAX_EMOTE_SET = 5;
|
|
4
|
+
/** An emote id on the wire: a seeded name (e.g. `heart`) or a generated id. */
|
|
5
|
+
export declare const EmoteIdSchema: Schema.filter<typeof Schema.String>;
|
|
6
|
+
/** A Player's chosen emotes, in their order. */
|
|
7
|
+
export declare const EmoteSetSchema: Schema.mutable<Schema.filter<Schema.Array$<Schema.filter<typeof Schema.String>>>>;
|
|
8
|
+
/** One live emote in the public gallery. */
|
|
9
|
+
export declare const EmoteSchema: Schema.Struct<{
|
|
10
|
+
id: typeof Schema.String;
|
|
11
|
+
title: typeof Schema.String;
|
|
12
|
+
description: typeof Schema.String;
|
|
13
|
+
/** Public, content-hashed image path; may be animated. */
|
|
14
|
+
src: typeof Schema.String;
|
|
15
|
+
/** First frame, shown when the viewer asks for reduced motion. */
|
|
16
|
+
stillSrc: typeof Schema.String;
|
|
17
|
+
}>;
|
|
18
|
+
export type Emote = typeof EmoteSchema.Type;
|
|
19
|
+
/** One pack in the public gallery: its live emotes in the Admin's order. */
|
|
20
|
+
export declare const EmotePackSchema: Schema.Struct<{
|
|
21
|
+
id: typeof Schema.String;
|
|
22
|
+
title: typeof Schema.String;
|
|
23
|
+
description: typeof Schema.String;
|
|
24
|
+
/** The pack whose first emotes a Player who chose nothing gets. */
|
|
25
|
+
isDefault: typeof Schema.Boolean;
|
|
26
|
+
emotes: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
27
|
+
id: typeof Schema.String;
|
|
28
|
+
title: typeof Schema.String;
|
|
29
|
+
description: typeof Schema.String;
|
|
30
|
+
/** Public, content-hashed image path; may be animated. */
|
|
31
|
+
src: typeof Schema.String;
|
|
32
|
+
/** First frame, shown when the viewer asks for reduced motion. */
|
|
33
|
+
stillSrc: typeof Schema.String;
|
|
34
|
+
}>>>;
|
|
35
|
+
}>;
|
|
36
|
+
export type EmotePack = typeof EmotePackSchema.Type;
|
|
37
|
+
/** Body of `GET /api/emotes`: every pack with live emotes, in pack order. */
|
|
38
|
+
export declare const EmoteGallerySchema: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
39
|
+
id: typeof Schema.String;
|
|
40
|
+
title: typeof Schema.String;
|
|
41
|
+
description: typeof Schema.String;
|
|
42
|
+
/** The pack whose first emotes a Player who chose nothing gets. */
|
|
43
|
+
isDefault: typeof Schema.Boolean;
|
|
44
|
+
emotes: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
45
|
+
id: typeof Schema.String;
|
|
46
|
+
title: typeof Schema.String;
|
|
47
|
+
description: typeof Schema.String;
|
|
48
|
+
/** Public, content-hashed image path; may be animated. */
|
|
49
|
+
src: typeof Schema.String;
|
|
50
|
+
/** First frame, shown when the viewer asks for reduced motion. */
|
|
51
|
+
stillSrc: typeof Schema.String;
|
|
52
|
+
}>>>;
|
|
53
|
+
}>>>;
|
|
54
|
+
/** Body of `GET /api/pages/admin/emotes`: every pack and emote, retired ones included. */
|
|
55
|
+
export declare const ManageEmotesPageSchema: Schema.Struct<{
|
|
56
|
+
packs: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
57
|
+
id: typeof Schema.String;
|
|
58
|
+
title: typeof Schema.String;
|
|
59
|
+
description: typeof Schema.String;
|
|
60
|
+
sortOrder: typeof Schema.Number;
|
|
61
|
+
isDefault: typeof Schema.Boolean;
|
|
62
|
+
emotes: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
63
|
+
sortOrder: typeof Schema.Number;
|
|
64
|
+
/** Hidden from the gallery and pickers; a Game in progress keeps showing it. */
|
|
65
|
+
retired: typeof Schema.Boolean;
|
|
66
|
+
id: typeof Schema.String;
|
|
67
|
+
title: typeof Schema.String;
|
|
68
|
+
description: typeof Schema.String;
|
|
69
|
+
src: typeof Schema.String;
|
|
70
|
+
stillSrc: typeof Schema.String;
|
|
71
|
+
}>>>;
|
|
72
|
+
}>>>;
|
|
4
73
|
}>;
|
|
5
|
-
export declare const SELECTABLE_EMOTE_IDS: readonly ["alert", "anger", "bars", "cash", "circle", "cloud", "cross", "dots1", "dots2", "dots3", "drop", "drops", "exclamation", "exclamations", "faceAngry", "faceHappy", "faceSad", "heart", "heartBroken", "hearts", "idea", "laugh", "music", "question", "sleep", "sleeps", "star", "stars", "swirl"];
|
package/dist/emotes.js
CHANGED
|
@@ -1,62 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"exclamations",
|
|
47
|
-
"faceAngry",
|
|
48
|
-
"faceHappy",
|
|
49
|
-
"faceSad",
|
|
50
|
-
"heart",
|
|
51
|
-
"heartBroken",
|
|
52
|
-
"hearts",
|
|
53
|
-
"idea",
|
|
54
|
-
"laugh",
|
|
55
|
-
"music",
|
|
56
|
-
"question",
|
|
57
|
-
"sleep",
|
|
58
|
-
"sleeps",
|
|
59
|
-
"star",
|
|
60
|
-
"stars",
|
|
61
|
-
"swirl",
|
|
62
|
-
];
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Most emotes a Player's set holds. */
|
|
3
|
+
export const MAX_EMOTE_SET = 5;
|
|
4
|
+
/** An emote id on the wire: a seeded name (e.g. `heart`) or a generated id. */
|
|
5
|
+
export const EmoteIdSchema = Schema.String.pipe(Schema.pattern(/^[A-Za-z0-9_-]{1,64}$/));
|
|
6
|
+
/** A Player's chosen emotes, in their order. */
|
|
7
|
+
export const EmoteSetSchema = Schema.mutable(Schema.Array(EmoteIdSchema).pipe(Schema.maxItems(MAX_EMOTE_SET)));
|
|
8
|
+
/** One live emote in the public gallery. */
|
|
9
|
+
export const EmoteSchema = Schema.Struct({
|
|
10
|
+
id: Schema.String,
|
|
11
|
+
title: Schema.String,
|
|
12
|
+
description: Schema.String,
|
|
13
|
+
/** Public, content-hashed image path; may be animated. */
|
|
14
|
+
src: Schema.String,
|
|
15
|
+
/** First frame, shown when the viewer asks for reduced motion. */
|
|
16
|
+
stillSrc: Schema.String,
|
|
17
|
+
});
|
|
18
|
+
/** One pack in the public gallery: its live emotes in the Admin's order. */
|
|
19
|
+
export const EmotePackSchema = Schema.Struct({
|
|
20
|
+
id: Schema.String,
|
|
21
|
+
title: Schema.String,
|
|
22
|
+
description: Schema.String,
|
|
23
|
+
/** The pack whose first emotes a Player who chose nothing gets. */
|
|
24
|
+
isDefault: Schema.Boolean,
|
|
25
|
+
emotes: Schema.mutable(Schema.Array(EmoteSchema)),
|
|
26
|
+
});
|
|
27
|
+
/** Body of `GET /api/emotes`: every pack with live emotes, in pack order. */
|
|
28
|
+
export const EmoteGallerySchema = Schema.mutable(Schema.Array(EmotePackSchema));
|
|
29
|
+
const ManagedEmoteSchema = Schema.Struct({
|
|
30
|
+
...EmoteSchema.fields,
|
|
31
|
+
sortOrder: Schema.Number,
|
|
32
|
+
/** Hidden from the gallery and pickers; a Game in progress keeps showing it. */
|
|
33
|
+
retired: Schema.Boolean,
|
|
34
|
+
});
|
|
35
|
+
/** Body of `GET /api/pages/admin/emotes`: every pack and emote, retired ones included. */
|
|
36
|
+
export const ManageEmotesPageSchema = Schema.Struct({
|
|
37
|
+
packs: Schema.mutable(Schema.Array(Schema.Struct({
|
|
38
|
+
id: Schema.String,
|
|
39
|
+
title: Schema.String,
|
|
40
|
+
description: Schema.String,
|
|
41
|
+
sortOrder: Schema.Number,
|
|
42
|
+
isDefault: Schema.Boolean,
|
|
43
|
+
emotes: Schema.mutable(Schema.Array(ManagedEmoteSchema)),
|
|
44
|
+
}))),
|
|
45
|
+
});
|
package/dist/error-codes.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type ErrorCode = "no_active_lobby" | "no_active_game" | "device_blocked" | "nickname_taken" | "nickname_locked" | "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";
|
|
1
|
+
export type ErrorCode = "no_active_lobby" | "no_active_game" | "device_blocked" | "nickname_taken" | "nickname_locked" | "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" | "emote_not_in_set" | "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";
|
package/dist/game.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { BadgeAward, BadgeId, BadgeMode, BadgeRunParams, } from "./badges.ts";
|
|
2
|
-
export {
|
|
2
|
+
export { type Emote, EmoteGallerySchema, EmoteIdSchema, type EmotePack, EmotePackSchema, EmoteSchema, EmoteSetSchema, MAX_EMOTE_SET, ManageEmotesPageSchema, } from "./emotes.ts";
|
|
3
3
|
export type { ErrorCode } from "./error-codes.ts";
|
|
4
4
|
export { type AdvanceMode, type Difficulty, type DifficultyFilter, GAME, type QuestionsPerRound, type ScoringMode, type TimerDuration, } from "./game.settings.ts";
|
|
5
5
|
export type { AccessMode, ActiveGamePhase, GamePhase, GameState, ImageMatchingQuizQuestion, Player, PlayerRole, PlayerStatus, QuizAnswer, QuizConfig, QuizQuestion, StandardQuizQuestion, } from "./game.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { EmoteGallerySchema, EmoteIdSchema, EmotePackSchema, EmoteSchema, EmoteSetSchema, MAX_EMOTE_SET, ManageEmotesPageSchema, } from "./emotes.js";
|
|
2
2
|
export { GAME, } from "./game.settings.js";
|
|
3
3
|
export * from "./pages/app.schema.js";
|
|
4
4
|
export * from "./pages/auth.schema.js";
|
|
@@ -19,6 +19,8 @@ export declare const ProfilePageSchema: Schema.Struct<{
|
|
|
19
19
|
role: Schema.Literal<["anonymous", "display", "member", "curator", "admin"]>;
|
|
20
20
|
powers: Schema.mutable<Schema.Array$<Schema.Schema<"can-access-mimic" | "can-send-feedback" | "can-import-quizzes" | "can-manage-features" | "can-add-questions" | "can-manage-categories" | "can-moderate-questions" | "can-publish-questions" | "is-power-user" | "can-manage-avatars" | "can-apply-for-curation" | "can-1v1", "can-access-mimic" | "can-send-feedback" | "can-import-quizzes" | "can-manage-features" | "can-add-questions" | "can-manage-categories" | "can-moderate-questions" | "can-publish-questions" | "is-power-user" | "can-manage-avatars" | "can-apply-for-curation" | "can-1v1", never>>>;
|
|
21
21
|
avatar: typeof Schema.String;
|
|
22
|
+
/** Saved emote set, in order. */
|
|
23
|
+
emoteIds: Schema.optional<Schema.mutable<Schema.filter<Schema.Array$<Schema.filter<typeof Schema.String>>>>>;
|
|
22
24
|
emailVerified: typeof Schema.Boolean;
|
|
23
25
|
}>;
|
|
24
26
|
theme: Schema.Struct<{
|
|
@@ -621,12 +623,7 @@ export declare const CuratorHistoryEntryPageSchema: Schema.Struct<{
|
|
|
621
623
|
readonly questionText?: string | undefined;
|
|
622
624
|
readonly mediaUrl?: string | undefined;
|
|
623
625
|
readonly mediaType?: "audio" | "video" | "image" | undefined;
|
|
624
|
-
readonly mediaCredit?:
|
|
625
|
-
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
626
|
-
readonly author?: string | undefined;
|
|
627
|
-
readonly sourceUrl?: string | undefined;
|
|
628
|
-
readonly licenceUrl?: string | undefined;
|
|
629
|
-
} | undefined;
|
|
626
|
+
readonly mediaCredit?: unknown;
|
|
630
627
|
}, never>>>>;
|
|
631
628
|
}>;
|
|
632
629
|
presetLimit: typeof Schema.Number;
|
package/dist/pages/app.schema.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { EmoteSetSchema } from "../emotes.js";
|
|
3
|
+
import { MediaTypeSchema, StoredMediaCreditSchema, StoredQuestionSourceSchema, } from "../question.schema.js";
|
|
3
4
|
import { ThemeModeSchema, UserPowerSchema, UserRoleSchema, } from "./common.schema.js";
|
|
4
5
|
/** Page-load response bodies for `src/api/routes/pages.ts`. */
|
|
5
6
|
/** A JSON array, decoded mutable — Effect's `Schema.Array` types its `.Type`
|
|
@@ -55,6 +56,8 @@ export const ProfilePageSchema = Schema.Struct({
|
|
|
55
56
|
role: UserRoleSchema,
|
|
56
57
|
powers: Arr(UserPowerSchema),
|
|
57
58
|
avatar: Schema.String,
|
|
59
|
+
/** Saved emote set, in order. */
|
|
60
|
+
emoteIds: Schema.optional(EmoteSetSchema),
|
|
58
61
|
emailVerified: Schema.Boolean,
|
|
59
62
|
}),
|
|
60
63
|
theme: Schema.Struct({ mode: ThemeModeSchema }),
|
|
@@ -338,7 +341,7 @@ const QuestionRecapEntrySchema = Schema.Struct({
|
|
|
338
341
|
questionText: Schema.optional(Schema.String),
|
|
339
342
|
mediaUrl: Schema.optional(Schema.String),
|
|
340
343
|
mediaType: Schema.optional(MediaTypeSchema),
|
|
341
|
-
mediaCredit: Schema.optional(
|
|
344
|
+
mediaCredit: Schema.optional(StoredMediaCreditSchema),
|
|
342
345
|
source: Schema.optional(StoredQuestionSourceSchema),
|
|
343
346
|
postAnswerNote: Schema.optional(Schema.String),
|
|
344
347
|
answered: Schema.Number,
|
|
@@ -19,12 +19,17 @@ export declare const GameAnswerRecordSchema: Schema.Struct<{
|
|
|
19
19
|
correctAnswerText: Schema.optional<typeof Schema.String>;
|
|
20
20
|
mediaUrl: Schema.optional<typeof Schema.String>;
|
|
21
21
|
mediaType: Schema.optional<Schema.Literal<["image", "audio", "video"]>>;
|
|
22
|
-
mediaCredit: Schema.optional<Schema.
|
|
23
|
-
licence:
|
|
24
|
-
author
|
|
25
|
-
sourceUrl
|
|
26
|
-
licenceUrl
|
|
27
|
-
}
|
|
22
|
+
mediaCredit: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
23
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
24
|
+
readonly author?: string | undefined;
|
|
25
|
+
readonly sourceUrl?: string | undefined;
|
|
26
|
+
readonly licenceUrl?: string | undefined;
|
|
27
|
+
}, {
|
|
28
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
29
|
+
readonly author?: string | undefined;
|
|
30
|
+
readonly sourceUrl?: string | undefined;
|
|
31
|
+
readonly licenceUrl?: string | undefined;
|
|
32
|
+
}, never>>>>;
|
|
28
33
|
source: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
29
34
|
readonly url: string;
|
|
30
35
|
readonly label?: string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { MediaTypeSchema, StoredMediaCreditSchema, StoredQuestionSourceSchema, } from "../question.schema.js";
|
|
3
3
|
/** Schemas shared by more than one page-load body. */
|
|
4
4
|
export const UserRoleSchema = Schema.Literal("anonymous", "display", "member", "curator", "admin");
|
|
5
5
|
export const UserPowerSchema = Schema.Literal("can-access-mimic", "can-send-feedback", "can-import-quizzes", "can-manage-features", "can-add-questions", "can-manage-categories", "can-moderate-questions", "can-publish-questions", "is-power-user", "can-manage-avatars", "can-apply-for-curation", "can-1v1");
|
|
@@ -20,7 +20,7 @@ export const GameAnswerRecordSchema = Schema.Struct({
|
|
|
20
20
|
correctAnswerText: Schema.optional(Schema.String),
|
|
21
21
|
mediaUrl: Schema.optional(Schema.String),
|
|
22
22
|
mediaType: Schema.optional(MediaTypeSchema),
|
|
23
|
-
mediaCredit: Schema.optional(
|
|
23
|
+
mediaCredit: Schema.optional(StoredMediaCreditSchema),
|
|
24
24
|
source: Schema.optional(StoredQuestionSourceSchema),
|
|
25
25
|
postAnswerNote: Schema.optional(Schema.String),
|
|
26
26
|
});
|
|
@@ -241,12 +241,17 @@ export declare const GameReviewPageSchema: Schema.Struct<{
|
|
|
241
241
|
correctAnswerText: Schema.optional<typeof Schema.String>;
|
|
242
242
|
mediaUrl: Schema.optional<typeof Schema.String>;
|
|
243
243
|
mediaType: Schema.optional<Schema.Literal<["image", "audio", "video"]>>;
|
|
244
|
-
mediaCredit: Schema.optional<Schema.
|
|
245
|
-
licence:
|
|
246
|
-
author
|
|
247
|
-
sourceUrl
|
|
248
|
-
licenceUrl
|
|
249
|
-
}
|
|
244
|
+
mediaCredit: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
245
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
246
|
+
readonly author?: string | undefined;
|
|
247
|
+
readonly sourceUrl?: string | undefined;
|
|
248
|
+
readonly licenceUrl?: string | undefined;
|
|
249
|
+
}, {
|
|
250
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
251
|
+
readonly author?: string | undefined;
|
|
252
|
+
readonly sourceUrl?: string | undefined;
|
|
253
|
+
readonly licenceUrl?: string | undefined;
|
|
254
|
+
}, never>>>>;
|
|
250
255
|
source: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
251
256
|
readonly url: string;
|
|
252
257
|
readonly label?: string | undefined;
|
|
@@ -302,12 +307,17 @@ export declare const SoloReviewPageSchema: Schema.Struct<{
|
|
|
302
307
|
questionId: Schema.NullOr<typeof Schema.String>;
|
|
303
308
|
mediaUrl: Schema.NullOr<typeof Schema.String>;
|
|
304
309
|
mediaType: Schema.NullOr<Schema.Literal<["image", "audio", "video"]>>;
|
|
305
|
-
mediaCredit: Schema.optional<Schema.
|
|
306
|
-
licence:
|
|
307
|
-
author
|
|
308
|
-
sourceUrl
|
|
309
|
-
licenceUrl
|
|
310
|
-
}
|
|
310
|
+
mediaCredit: Schema.optional<Schema.Union<[typeof Schema.Null, Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
311
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
312
|
+
readonly author?: string | undefined;
|
|
313
|
+
readonly sourceUrl?: string | undefined;
|
|
314
|
+
readonly licenceUrl?: string | undefined;
|
|
315
|
+
}, {
|
|
316
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
317
|
+
readonly author?: string | undefined;
|
|
318
|
+
readonly sourceUrl?: string | undefined;
|
|
319
|
+
readonly licenceUrl?: string | undefined;
|
|
320
|
+
}, never>>>]>>;
|
|
311
321
|
source: Schema.Union<[typeof Schema.Null, Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
312
322
|
readonly url: string;
|
|
313
323
|
readonly label?: string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { MediaTypeSchema, StoredMediaCreditSchema, StoredQuestionSourceSchema, } from "../question.schema.js";
|
|
3
3
|
import { GameAnswerRecordSchema, PlayerRoleSchema, UserPowerSchema, UserRoleSchema, } from "./common.schema.js";
|
|
4
4
|
/** Page-load response bodies for `src/api/routes/pages-history.ts and admin-feature-flags.ts`. */
|
|
5
5
|
/** Achievement badge id (mirrors `BadgeId` in `src/lib/badges.ts`). */
|
|
@@ -208,7 +208,8 @@ const SoloRunReviewEntrySchema = Schema.Struct({
|
|
|
208
208
|
mediaUrl: Schema.NullOr(Schema.String),
|
|
209
209
|
mediaType: Schema.NullOr(MediaTypeSchema),
|
|
210
210
|
// Optional: a review served before credits existed has no key.
|
|
211
|
-
|
|
211
|
+
// Null first: the stored-credit transform accepts any value, null included.
|
|
212
|
+
mediaCredit: Schema.optional(Schema.Union(Schema.Null, StoredMediaCreditSchema)),
|
|
212
213
|
// Null first: the stored-source transform accepts any value, null included.
|
|
213
214
|
source: Schema.Union(Schema.Null, StoredQuestionSourceSchema),
|
|
214
215
|
postAnswerNote: Schema.NullOr(Schema.String),
|
|
@@ -92,6 +92,22 @@ export declare const QuizContextPageSchema: Schema.Struct<{
|
|
|
92
92
|
src: typeof Schema.String;
|
|
93
93
|
}>>>;
|
|
94
94
|
emotesEnabled: typeof Schema.Boolean;
|
|
95
|
+
/** The emote gallery the setup picker offers and the play page draws from. */
|
|
96
|
+
emotePacks: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
97
|
+
id: typeof Schema.String;
|
|
98
|
+
title: typeof Schema.String;
|
|
99
|
+
description: typeof Schema.String;
|
|
100
|
+
isDefault: typeof Schema.Boolean;
|
|
101
|
+
emotes: Schema.mutable<Schema.Array$<Schema.Struct<{
|
|
102
|
+
id: typeof Schema.String;
|
|
103
|
+
title: typeof Schema.String;
|
|
104
|
+
description: typeof Schema.String;
|
|
105
|
+
src: typeof Schema.String;
|
|
106
|
+
stillSrc: typeof Schema.String;
|
|
107
|
+
}>>>;
|
|
108
|
+
}>>>;
|
|
109
|
+
/** The signed-in Player's saved emote set; absent for a guest. */
|
|
110
|
+
profileEmoteIds: Schema.optional<Schema.mutable<Schema.filter<Schema.Array$<Schema.filter<typeof Schema.String>>>>>;
|
|
95
111
|
lobby: Schema.NullOr<Schema.Struct<{
|
|
96
112
|
quizName: typeof Schema.String;
|
|
97
113
|
description: typeof Schema.String;
|
|
@@ -104,6 +120,7 @@ export declare const QuizContextPageSchema: Schema.Struct<{
|
|
|
104
120
|
id: typeof Schema.String;
|
|
105
121
|
nickname: typeof Schema.String;
|
|
106
122
|
avatar: typeof Schema.String;
|
|
123
|
+
emotes: Schema.mutable<Schema.Array$<typeof Schema.String>>;
|
|
107
124
|
score: typeof Schema.Number;
|
|
108
125
|
status: Schema.Literal<["pending", "active", "disconnected"]>;
|
|
109
126
|
role: Schema.Literal<["player", "observer"]>;
|
|
@@ -135,12 +152,17 @@ export declare const QuizResultsPageSchema: Schema.Struct<{
|
|
|
135
152
|
correctAnswerText: Schema.optional<typeof Schema.String>;
|
|
136
153
|
mediaUrl: Schema.optional<typeof Schema.String>;
|
|
137
154
|
mediaType: Schema.optional<Schema.Literal<["image", "audio", "video"]>>;
|
|
138
|
-
mediaCredit: Schema.optional<Schema.
|
|
139
|
-
licence:
|
|
140
|
-
author
|
|
141
|
-
sourceUrl
|
|
142
|
-
licenceUrl
|
|
143
|
-
}
|
|
155
|
+
mediaCredit: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
156
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
157
|
+
readonly author?: string | undefined;
|
|
158
|
+
readonly sourceUrl?: string | undefined;
|
|
159
|
+
readonly licenceUrl?: string | undefined;
|
|
160
|
+
}, {
|
|
161
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
162
|
+
readonly author?: string | undefined;
|
|
163
|
+
readonly sourceUrl?: string | undefined;
|
|
164
|
+
readonly licenceUrl?: string | undefined;
|
|
165
|
+
}, never>>>>;
|
|
144
166
|
source: Schema.optional<Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
145
167
|
readonly url: string;
|
|
146
168
|
readonly label?: string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import { EmotePackSchema, EmoteSetSchema } from "../emotes.js";
|
|
2
3
|
import { GAME } from "../game.settings.js";
|
|
3
4
|
import { GameAnswerRecordSchema, PlayerRoleSchema, SkyPhaseSchema, ThemeModeSchema, UserPowerSchema, UserRoleSchema, } from "./common.schema.js";
|
|
4
5
|
/** Page-load response bodies for `src/api/routes/layout.ts and quiz.ts`. */
|
|
@@ -93,6 +94,7 @@ const LobbySchema = Schema.Struct({
|
|
|
93
94
|
id: Schema.String,
|
|
94
95
|
nickname: Schema.String,
|
|
95
96
|
avatar: Schema.String,
|
|
97
|
+
emotes: Schema.mutable(Schema.Array(Schema.String)),
|
|
96
98
|
score: Schema.Number,
|
|
97
99
|
status: PlayerStatusSchema,
|
|
98
100
|
role: PlayerRoleSchema,
|
|
@@ -110,6 +112,10 @@ export const QuizContextPageSchema = Schema.Struct({
|
|
|
110
112
|
profileAvatarId: Schema.String,
|
|
111
113
|
avatars: Schema.mutable(Schema.Array(AvatarSchema)),
|
|
112
114
|
emotesEnabled: Schema.Boolean,
|
|
115
|
+
/** The emote gallery the setup picker offers and the play page draws from. */
|
|
116
|
+
emotePacks: Schema.mutable(Schema.Array(EmotePackSchema)),
|
|
117
|
+
/** The signed-in Player's saved emote set; absent for a guest. */
|
|
118
|
+
profileEmoteIds: Schema.optional(EmoteSetSchema),
|
|
113
119
|
lobby: Schema.NullOr(LobbySchema),
|
|
114
120
|
// Replayed game WS frames, opaque here — applyStateMessages reads their
|
|
115
121
|
// fields by message `type` on the client, so decoding preserves every key
|
|
@@ -24,6 +24,22 @@ export declare const MediaCreditSchema: Schema.filter<Schema.Struct<{
|
|
|
24
24
|
licenceUrl: Schema.optional<Schema.filter<Schema.filter<typeof Schema.String>>>;
|
|
25
25
|
}>>;
|
|
26
26
|
export type MediaCredit = typeof MediaCreditSchema.Type;
|
|
27
|
+
/**
|
|
28
|
+
* Read-side credit: a stored value that fails `MediaCreditSchema` (a rule
|
|
29
|
+
* tightened after it was written, a wrong shape) decodes to undefined, so one
|
|
30
|
+
* bad credit never fails a whole page.
|
|
31
|
+
*/
|
|
32
|
+
export declare const StoredMediaCreditSchema: Schema.transform<typeof Schema.Unknown, Schema.UndefinedOr<Schema.SchemaClass<{
|
|
33
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
34
|
+
readonly author?: string | undefined;
|
|
35
|
+
readonly sourceUrl?: string | undefined;
|
|
36
|
+
readonly licenceUrl?: string | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
readonly licence: "cc0" | "public-domain" | "cc-by" | "cc-by-sa" | "own";
|
|
39
|
+
readonly author?: string | undefined;
|
|
40
|
+
readonly sourceUrl?: string | undefined;
|
|
41
|
+
readonly licenceUrl?: string | undefined;
|
|
42
|
+
}, never>>>;
|
|
27
43
|
export declare const MediaSchema: Schema.Struct<{
|
|
28
44
|
type: Schema.Literal<["image", "audio", "video"]>;
|
|
29
45
|
url: typeof Schema.String;
|
package/dist/question.schema.js
CHANGED
|
@@ -57,6 +57,17 @@ export const MediaCreditSchema = Schema.Struct({
|
|
|
57
57
|
}).pipe(Schema.filter((c) => !ATTRIBUTION_LICENCES.includes(c.licence) ||
|
|
58
58
|
Boolean(c.author?.trim()) ||
|
|
59
59
|
"Author is required for CC BY and CC BY-SA"));
|
|
60
|
+
const isMediaCredit = Schema.is(MediaCreditSchema);
|
|
61
|
+
/**
|
|
62
|
+
* Read-side credit: a stored value that fails `MediaCreditSchema` (a rule
|
|
63
|
+
* tightened after it was written, a wrong shape) decodes to undefined, so one
|
|
64
|
+
* bad credit never fails a whole page.
|
|
65
|
+
*/
|
|
66
|
+
export const StoredMediaCreditSchema = Schema.transform(Schema.Unknown, Schema.UndefinedOr(Schema.typeSchema(MediaCreditSchema)), {
|
|
67
|
+
strict: true,
|
|
68
|
+
decode: (credit) => (isMediaCredit(credit) ? credit : undefined),
|
|
69
|
+
encode: (credit) => credit,
|
|
70
|
+
});
|
|
60
71
|
export const MediaSchema = Schema.Struct({
|
|
61
72
|
type: MediaTypeSchema,
|
|
62
73
|
url: Schema.String,
|
package/dist/ws-game.schema.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare const ClientMessageSchema: Schema.Union<[Schema.Struct<{
|
|
|
8
8
|
playerId: Schema.optional<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
9
9
|
}>, Schema.Struct<{
|
|
10
10
|
type: Schema.Literal<["player:emote"]>;
|
|
11
|
-
emoteId: Schema.
|
|
11
|
+
emoteId: Schema.filter<typeof Schema.String>;
|
|
12
12
|
offsetX: Schema.filter<Schema.filter<typeof Schema.Number>>;
|
|
13
13
|
offsetY: Schema.filter<Schema.filter<typeof Schema.Number>>;
|
|
14
14
|
}>, Schema.Struct<{
|
package/dist/ws-game.schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { EmoteIdSchema } from "./emotes.js";
|
|
3
3
|
import { GAME } from "./game.settings.js";
|
|
4
4
|
import { DifficultySchema, MediaCreditSchema, MediaTypeSchema, } from "./question.schema.js";
|
|
5
5
|
import { OptionalScoringModeSchema } from "./scoring.schema.js";
|
|
@@ -31,7 +31,8 @@ const PlayerAnswerMessageSchema = Schema.Struct({
|
|
|
31
31
|
});
|
|
32
32
|
const PlayerEmoteMessageSchema = Schema.Struct({
|
|
33
33
|
type: Schema.Literal("player:emote"),
|
|
34
|
-
|
|
34
|
+
// Any well-formed id; the server refuses one outside the sender's set.
|
|
35
|
+
emoteId: EmoteIdSchema,
|
|
35
36
|
// Broadcast to every player and used directly as CSS left%/top% (0-1) —
|
|
36
37
|
// bounded, not just finite, or an attacker-controlled value corrupts the
|
|
37
38
|
// shared emote overlay for the whole lobby.
|