@roster-lock/types 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/LICENSE.md +11 -0
  2. package/dist/index.js +18 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/v1/draft/index.js +3 -0
  5. package/dist/v1/draft/index.js.map +1 -0
  6. package/dist/v1/index.js +24 -0
  7. package/dist/v1/index.js.map +1 -0
  8. package/dist/v1/lock/engine.js +3 -0
  9. package/dist/v1/lock/engine.js.map +1 -0
  10. package/dist/v1/lock/index.js +21 -0
  11. package/dist/v1/lock/index.js.map +1 -0
  12. package/dist/v1/lock/piece-meta.js +3 -0
  13. package/dist/v1/lock/piece-meta.js.map +1 -0
  14. package/dist/v1/lock/roster.js +3 -0
  15. package/dist/v1/lock/roster.js.map +1 -0
  16. package/dist/v1/lock/selection/index.js +18 -0
  17. package/dist/v1/lock/selection/index.js.map +1 -0
  18. package/dist/v1/lock/selection/meta.js +3 -0
  19. package/dist/v1/lock/selection/meta.js.map +1 -0
  20. package/dist/v1/lock/selection/script.js +3 -0
  21. package/dist/v1/lock/selection/script.js.map +1 -0
  22. package/dist/v1/lock/selection/selection-types/game-controlled.js +3 -0
  23. package/dist/v1/lock/selection/selection-types/game-controlled.js.map +1 -0
  24. package/dist/v1/lock/selection/selection-types/normal.js +3 -0
  25. package/dist/v1/lock/selection/selection-types/normal.js.map +1 -0
  26. package/dist/v1/lock/selection/selection-types/preselected.js +3 -0
  27. package/dist/v1/lock/selection/selection-types/preselected.js.map +1 -0
  28. package/dist/v1/lock/selection/selection-types/unselectable.js +3 -0
  29. package/dist/v1/lock/selection/selection-types/unselectable.js.map +1 -0
  30. package/dist/v1/metadata.js +3 -0
  31. package/dist/v1/metadata.js.map +1 -0
  32. package/dist/v1/relay/index.js +3 -0
  33. package/dist/v1/relay/index.js.map +1 -0
  34. package/dist/v1/request/index.js +20 -0
  35. package/dist/v1/request/index.js.map +1 -0
  36. package/dist/v1/request/input/agent-to-relay.js +3 -0
  37. package/dist/v1/request/input/agent-to-relay.js.map +1 -0
  38. package/dist/v1/request/input/client-to-agent.js +3 -0
  39. package/dist/v1/request/input/client-to-agent.js.map +1 -0
  40. package/dist/v1/request/input/index.js +20 -0
  41. package/dist/v1/request/input/index.js.map +1 -0
  42. package/dist/v1/request/input/user-to-client.js +3 -0
  43. package/dist/v1/request/input/user-to-client.js.map +1 -0
  44. package/dist/v1/request/output/download-event.js +14 -0
  45. package/dist/v1/request/output/download-event.js.map +1 -0
  46. package/dist/v1/request/output/index.js +18 -0
  47. package/dist/v1/request/output/index.js.map +1 -0
  48. package/dist/v1/request/shared.js +3 -0
  49. package/dist/v1/request/shared.js.map +1 -0
  50. package/dist/v1/runtime/download/Archive.js +3 -0
  51. package/dist/v1/runtime/download/Archive.js.map +1 -0
  52. package/dist/v1/runtime/download/Decompressor.js +3 -0
  53. package/dist/v1/runtime/download/Decompressor.js.map +1 -0
  54. package/dist/v1/runtime/download/Protocol.js +3 -0
  55. package/dist/v1/runtime/download/Protocol.js.map +1 -0
  56. package/dist/v1/runtime/download/index.js +21 -0
  57. package/dist/v1/runtime/download/index.js.map +1 -0
  58. package/dist/v1/runtime/download/types.js +3 -0
  59. package/dist/v1/runtime/download/types.js.map +1 -0
  60. package/dist/v1/runtime/index.js +20 -0
  61. package/dist/v1/runtime/index.js.map +1 -0
  62. package/dist/v1/runtime/piece-selection-sort/index.js +3 -0
  63. package/dist/v1/runtime/piece-selection-sort/index.js.map +1 -0
  64. package/dist/v1/runtime/unstrusted-script/index.js +18 -0
  65. package/dist/v1/runtime/unstrusted-script/index.js.map +1 -0
  66. package/dist/v1/runtime/unstrusted-script/purpose-input.js +3 -0
  67. package/dist/v1/runtime/unstrusted-script/purpose-input.js.map +1 -0
  68. package/dist/v1/shared.js +3 -0
  69. package/dist/v1/shared.js.map +1 -0
  70. package/package.json +25 -0
  71. package/src/index.ts +2 -0
  72. package/src/v1/draft/index.ts +32 -0
  73. package/src/v1/index.ts +8 -0
  74. package/src/v1/lock/engine.ts +40 -0
  75. package/src/v1/lock/index.ts +24 -0
  76. package/src/v1/lock/piece-meta.ts +9 -0
  77. package/src/v1/lock/roster.ts +27 -0
  78. package/src/v1/lock/selection/index.ts +34 -0
  79. package/src/v1/lock/selection/meta.ts +17 -0
  80. package/src/v1/lock/selection/script.ts +56 -0
  81. package/src/v1/lock/selection/selection-types/game-controlled.ts +9 -0
  82. package/src/v1/lock/selection/selection-types/normal.ts +32 -0
  83. package/src/v1/lock/selection/selection-types/preselected.ts +12 -0
  84. package/src/v1/lock/selection/selection-types/unselectable.ts +3 -0
  85. package/src/v1/metadata.ts +10 -0
  86. package/src/v1/relay/index.ts +19 -0
  87. package/src/v1/request/index.ts +4 -0
  88. package/src/v1/request/input/agent-to-relay.ts +6 -0
  89. package/src/v1/request/input/client-to-agent.ts +19 -0
  90. package/src/v1/request/input/index.ts +4 -0
  91. package/src/v1/request/input/user-to-client.ts +21 -0
  92. package/src/v1/request/output/download-event.ts +49 -0
  93. package/src/v1/request/output/index.ts +34 -0
  94. package/src/v1/request/shared.ts +13 -0
  95. package/src/v1/runtime/download/Archive.ts +13 -0
  96. package/src/v1/runtime/download/Decompressor.ts +6 -0
  97. package/src/v1/runtime/download/Protocol.ts +15 -0
  98. package/src/v1/runtime/download/index.ts +5 -0
  99. package/src/v1/runtime/download/types.ts +18 -0
  100. package/src/v1/runtime/index.ts +4 -0
  101. package/src/v1/runtime/piece-selection-sort/index.ts +34 -0
  102. package/src/v1/runtime/unstrusted-script/index.ts +59 -0
  103. package/src/v1/runtime/unstrusted-script/purpose-input.ts +34 -0
  104. package/src/v1/shared.ts +14 -0
  105. package/tsconfig.json +20 -0
@@ -0,0 +1,24 @@
1
+ import { RosterLockIdentity } from "../shared";
2
+ import { RosterLockEngineConfig } from "./engine";
3
+ import { RosterLockPiece } from "./roster";
4
+ import { RosterLockSelectionConfig } from "./selection";
5
+ import { RosterLockPieceMeta } from "./piece-meta";
6
+
7
+ export * from "./engine";
8
+ export * from "./roster";
9
+ export * from "./selection";
10
+ export * from "./piece-meta";
11
+
12
+
13
+ export type RosterLockV1Config = {
14
+ configIdentity: RosterLockIdentity<"lock", 1>,
15
+
16
+ author: string,
17
+ title: string,
18
+ version: string,
19
+ engine: RosterLockEngineConfig,
20
+ rosters: Record<string, Array<RosterLockPiece>>,
21
+ selection: RosterLockSelectionConfig,
22
+ pieceMeta: RosterLockPieceMeta,
23
+ }
24
+
@@ -0,0 +1,9 @@
1
+ import { PieceType } from "../shared";
2
+ import { JSONShallowObject, SelectionPieceMeta } from "./selection/meta";
3
+
4
+ /*
5
+ Custom fields (tier, difficulty, tags, etc) that selection configs can validate against
6
+ and merge algorithms/scripts can read via PIECE_META.get(). Kept out of the selection
7
+ config itself so the same selection config can be reused across different rosters.
8
+ */
9
+ export type RosterLockPieceMeta = Record<PieceType, SelectionPieceMeta<JSONShallowObject>>;
@@ -0,0 +1,27 @@
1
+
2
+ import { PieceId, Sha256 } from "../shared";
3
+
4
+ type URLType = string;
5
+ type DownloadableSource = string;
6
+
7
+ export type RosterLockPiece = {
8
+ id: PieceId,
9
+ version: {
10
+ logic: Sha256,
11
+ media: Sha256,
12
+ docs: Sha256,
13
+ },
14
+ humanInfo: {
15
+ name: string,
16
+ author: string,
17
+ url: URLType,
18
+ image?: URLType,
19
+ }
20
+ downloadSources: Array<DownloadableSource>,
21
+ pathVariables: Record<string, string>,
22
+ requiredPieces: Record<string, {
23
+ expected: Array<PieceId>,
24
+ selectable: boolean,
25
+ }>,
26
+ };
27
+
@@ -0,0 +1,34 @@
1
+
2
+ import { PieceType } from "../../shared";
3
+ import { UntrustedScriptRef } from "./script";
4
+ import { SelectionGameControlledConfig } from "./selection-types/game-controlled";
5
+ import { SelectionNormalConfig, UserSelectionValidation } from "./selection-types/normal";
6
+ import { SelectionPreselectedConfig } from "./selection-types/preselected";
7
+ import { SelectionUnselectableConfig } from "./selection-types/unselectable";
8
+
9
+ export * from "./meta";
10
+
11
+ export {
12
+ SelectionPreselectedConfig,
13
+ SelectionGameControlledConfig,
14
+ SelectionNormalConfig,
15
+ SelectionUnselectableConfig,
16
+ UserSelectionValidation,
17
+ };
18
+
19
+ export { UntrustedScriptRef };
20
+
21
+ export type RosterLockSelectionConfig = {
22
+ piece: Record<PieceType, (
23
+ | SelectionGameControlledConfig
24
+ | SelectionNormalConfig
25
+ | SelectionPreselectedConfig
26
+ | SelectionUnselectableConfig
27
+ )>,
28
+
29
+ globalValidation: Array<UntrustedScriptRef>
30
+
31
+ scriptDictionary: Record<string, { content: string, }>
32
+ };
33
+
34
+
@@ -0,0 +1,17 @@
1
+ import { PieceId } from "../../shared";
2
+
3
+ export type JSONShallowObject = Record<string, (
4
+ | string | number | boolean
5
+ | Array<string> | Array<number> | Array<boolean>
6
+ )>;
7
+
8
+ type SimpleSchemaType = (
9
+ | "boolean" | "number" | "string"
10
+ | "boolean[]" | "number[]" | "string[]"
11
+ )
12
+
13
+ export type SelectionPieceMeta<Config extends JSONShallowObject> = {
14
+ schema: Record<string, SimpleSchemaType>,
15
+ defaultMeta: Config,
16
+ values: Record<PieceId, Partial<Config>>,
17
+ }
@@ -0,0 +1,56 @@
1
+ /*
2
+ Global Variables accessible to the script
3
+
4
+ // This is psuedo random number generator based on seeds from all players during the commit/reveal step
5
+ // It returns a float between 0 and 1
6
+ RANDOM()
7
+
8
+ // This is a map of all the piece meta
9
+ // Normally only includes the current piece type and any "on demand" piece types that are required by the current piece type
10
+ // for globalValidation it includes all piece types after merging
11
+ // This is a getter as it will merge default meta with a piece's custom meta
12
+ PIECE_META.get(pieceType: string, pieceId: string): Meta
13
+
14
+ // The pieces available to be selected
15
+ // Normally only includes the current piece type and any "on demand" piece types that are required by the current piece type
16
+ // for globalValidation it includes all piece types after merging
17
+ PIECES_AVAILABLE: {
18
+ [pieceType: string]: Array<PieceId>
19
+ }
20
+
21
+ type SelectedPiece = {
22
+ // The id of the piece
23
+ id: pieceId,
24
+ // Whether the piece was selected or required by the piece config
25
+ selected: "selected" | "required",
26
+ // The "on demand" pieces that are required by this piece
27
+ // Includes both the selected and the pieces defined in the piece's config
28
+ required: Record<pieceType, Array<SelectedPiece>>,
29
+ }
30
+
31
+
32
+ // The pieces selected by the current player - only available during individual validation
33
+ PLAYER_SELECTION: Array<SelectedPiece>
34
+
35
+
36
+ // The pieces selected by each player - only available during merge algorithms
37
+ EACH_PLAYER_SELECTION: {
38
+ [userId: string]: Array<SelectedPiece>
39
+ }
40
+
41
+ // The final merged selection - only available during globalValidation
42
+ FINAL_SELECTION: {
43
+ // depending on the pieceType, it's either a list of pieces or a list of pieces per player
44
+ [pieceType: string]: Array<SelectedPiece> | Record<userId, Array<SelectedPiece>>
45
+ }
46
+
47
+ */
48
+ type RelativePath = string;
49
+ export type UntrustedScriptRef = (
50
+ // I'm thinking a "published" config will be a tarball of all necessary files
51
+ // This allows users to write scripts in their preferred editor then add them as necessary
52
+ | {
53
+ src: RelativePath,
54
+ method?: string,
55
+ }
56
+ );
@@ -0,0 +1,9 @@
1
+
2
+
3
+ // The game will handle the selection however it wants
4
+ // The selection should be sent along side the match lock config when creating a room
5
+
6
+ // Room will handle the selection as if it were a "preselected" config
7
+ export type SelectionGameControlledConfig = {
8
+ type: "game-controlled",
9
+ };
@@ -0,0 +1,32 @@
1
+ import { UntrustedScriptRef } from "../script";
2
+ import { PieceId, Count } from "../../../shared";
3
+
4
+ export type UserSelectionValidation = {
5
+ count: Count,
6
+ unique: boolean,
7
+ banList: Array<PieceId>,
8
+ customValidation: Array<UntrustedScriptRef>
9
+ };
10
+
11
+
12
+ export type SelectionNormalConfig = {
13
+ type: "normal",
14
+
15
+ /*
16
+ The validation is used to validate the current user's and other player's choices
17
+ The validation does not validate the final choices after the merge algorithm is run
18
+ */
19
+ validation: UserSelectionValidation,
20
+
21
+ /*
22
+ A merge algorithm takes in each player's choices and returns a new set of choices
23
+ If the pieceType is "personal", the merge algorithm is expected to return a set of choices per player
24
+ If the pieceType is "shared", the merge algorithm is expected to return a single set of choices
25
+ - the mergeAlgorithm is mandatory for "shared" pieces
26
+ If the pieceType is "on demand", the merge algorithm is not allowed
27
+
28
+ We validate the return type of the algorithm to ensure it matches the pieceType
29
+ */
30
+ mergeAlgorithm?: UntrustedScriptRef
31
+ };
32
+
@@ -0,0 +1,12 @@
1
+
2
+ // Can select pieces as a part of the config
3
+ // This is useful if players just want to play a specific stage without the chance of another being chosen
4
+ // Final Destination Fox only
5
+
6
+ import { SelectedPiece } from "../../../request/shared";
7
+
8
+ // When selecting personal pieces, the array will be applied to all players
9
+ export type SelectionPreselectedConfig = {
10
+ type: "preselected",
11
+ pieces: Array<SelectedPiece>
12
+ };
@@ -0,0 +1,3 @@
1
+ export type SelectionUnselectableConfig = {
2
+ type: "unselectable",
3
+ };
@@ -0,0 +1,10 @@
1
+
2
+ import { RosterLockPiece } from "./lock/roster";
3
+ import { RosterLockIdentity } from "./shared";
4
+
5
+ export type RosterLockV1PieceInfo = (
6
+ & {
7
+ configIdentity: RosterLockIdentity<"piece-info", 1>
8
+ }
9
+ & Pick<RosterLockPiece, "humanInfo" | "downloadSources" | "pathVariables">
10
+ )
@@ -0,0 +1,19 @@
1
+
2
+ // Room Creation
3
+ export type RoomConfig = {
4
+ matchmakerId: string;
5
+ coordinatorId: string;
6
+ roomId: string;
7
+ rosterConfigHash: string;
8
+ machines: RoomMachine[];
9
+ }
10
+
11
+ export type RoomMachine = {
12
+ machineId: string;
13
+ publicKey: string;
14
+ displayName: string;
15
+ // How many local players this machine is bringing to the room, declared to
16
+ // the matchmaker at queue time - match-agent validates each machine's
17
+ // submitted selections against this count.
18
+ playerCount: number;
19
+ }
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./shared"
3
+ export * from "./input"
4
+ export * from "./output"
@@ -0,0 +1,6 @@
1
+ import { UserSelection } from "../shared";
2
+
3
+ export type UserInput = {
4
+ randomSeed: string,
5
+ userSelection: UserSelection
6
+ };
@@ -0,0 +1,19 @@
1
+ import { RosterLockV1Config } from "../../lock";
2
+
3
+ import { UserSelection } from "../shared";
4
+
5
+ export type RosterLockV1SyncDLRequestClientToAgent = {
6
+ relay: {
7
+ url: string,
8
+ roomId: string,
9
+ },
10
+ machine: {
11
+ timestamp: number,
12
+ publicKey: string,
13
+ signature: string,
14
+ },
15
+ rosterConfig: RosterLockV1Config,
16
+ // Keyed by local player index on this machine (0-based) - a machine with
17
+ // multiple local players (e.g. 2 controllers) submits one entry per player.
18
+ playerSelections: Record<number, UserSelection>,
19
+ };
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./user-to-client";
3
+ export * from "./client-to-agent";
4
+ export * from "./agent-to-relay";
@@ -0,0 +1,21 @@
1
+ import { RosterLockV1Config } from "../../lock";
2
+
3
+ import { UserSelection } from "../shared";
4
+
5
+ export type RosterLockV1SyncDLRequestUserToClient = {
6
+ version: 1,
7
+ relay: {
8
+ url: string,
9
+ roomId: string,
10
+ },
11
+ machine: {
12
+ machineId: string;
13
+ keys: {
14
+ publicKey: string,
15
+ privateKey: string,
16
+ }
17
+ },
18
+ rosterConfig: RosterLockV1Config,
19
+ // Keyed by local player index on this machine (0-based).
20
+ playerSelections: Record<number, UserSelection>,
21
+ };
@@ -0,0 +1,49 @@
1
+
2
+ export enum ROSTERLOCK_DOWNLOAD_STATE {
3
+ downloadStart = "download-start",
4
+ downloadProgress = "download-progress",
5
+ downloadValidation = "download-validation",
6
+ downloadFinished = "download-finished",
7
+ downloadFailure = "download-failure",
8
+
9
+ downloadAllComplete = "download-all-complete",
10
+ downloadFullFailure = "download-full-fail",
11
+ }
12
+
13
+ export type RosterLockDownloadUpdate = (
14
+ | {
15
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadStart,
16
+ pieceType: string,
17
+ pieceVersions: { logic: string, media: string },
18
+ }
19
+ | {
20
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadProgress,
21
+ pieceType: string,
22
+ pieceVersions: { logic: string, media: string },
23
+ progress: number,
24
+ }
25
+ | {
26
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadValidation,
27
+ pieceType: string,
28
+ pieceVersions: { logic: string, media: string },
29
+ }
30
+ | {
31
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadFinished,
32
+ pieceType: string,
33
+ pieceVersions: { logic: string, media: string },
34
+ }
35
+ | {
36
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadFailure,
37
+ pieceType: string,
38
+ pieceVersions: { logic: string, media: string },
39
+ error: string,
40
+ }
41
+ | {
42
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadAllComplete,
43
+ }
44
+ | {
45
+ type: ROSTERLOCK_DOWNLOAD_STATE.downloadFullFailure,
46
+ error: string,
47
+ }
48
+ )
49
+
@@ -0,0 +1,34 @@
1
+
2
+ import { PlayerId, PieceType, PieceId } from "../../shared";
3
+ import { SelectedPiece } from "../shared";
4
+
5
+ export * from "./download-event";
6
+
7
+ export type SharedSelection = {
8
+ type: "shared",
9
+ value: Array<SelectedPiece>,
10
+ };
11
+ export type PersonalSelection = {
12
+ type: "personal",
13
+ value: Record<PlayerId, Array<SelectedPiece>>,
14
+ };
15
+
16
+ export type FinalSelection = Record<PieceType, (
17
+ | SharedSelection
18
+ | PersonalSelection
19
+ )>;
20
+
21
+ export type DownloadResult = {
22
+ pieceType: PieceType,
23
+ pieceId: PieceId,
24
+ pieceVersions: { logic: string, media: string },
25
+ folder: string,
26
+ }
27
+
28
+ export type DownloadResultsMap = Record<PieceType, Record<PieceId, DownloadResult>>;
29
+
30
+ export type RosterLockV1SyncDLResult = {
31
+ finalSelection: FinalSelection,
32
+ downloadResults: DownloadResultsMap,
33
+ }
34
+
@@ -0,0 +1,13 @@
1
+ import { PieceId, PieceType } from "../shared";
2
+
3
+ export type SelectedPiece = {
4
+ id: PieceId,
5
+ // selected: "selected" | "required",
6
+ required: Record<PieceType, {
7
+ mandatory: Array<SelectedPiece>,
8
+ selectable: Array<SelectedPiece>
9
+ }>
10
+ };
11
+
12
+
13
+ export type UserSelection = Record<PieceType, Array<SelectedPiece>>;
@@ -0,0 +1,13 @@
1
+
2
+
3
+ export type ArchiveFile = {
4
+ path: string,
5
+ contents: AsyncIterable<Uint8Array>
6
+ };
7
+
8
+ export type ArchiveHandler = {
9
+ name: string;
10
+ extensions: Array<string>,
11
+ extractFiles: (input: AsyncIterable<Uint8Array>)=>AsyncIterable<ArchiveFile>;
12
+ };
13
+
@@ -0,0 +1,6 @@
1
+
2
+ export type Decompressor = {
3
+ name: string;
4
+ extensions: Array<string>,
5
+ decompress: (input: AsyncIterable<Uint8Array>) => AsyncIterable<Uint8Array>;
6
+ };
@@ -0,0 +1,15 @@
1
+
2
+ import { ProcessHandlers } from "./types";
3
+
4
+ export type ProtocolHandler = {
5
+ name: string,
6
+ validateURL: (url: string)=>boolean
7
+ download: (
8
+ url: string,
9
+ folderDestination: string,
10
+ processHandlers: ProcessHandlers
11
+ ) => Promise<{
12
+ finishPromise: Promise<any>,
13
+ metaData?: any
14
+ }>;
15
+ };
@@ -0,0 +1,5 @@
1
+
2
+ export * from "./types";
3
+ export * from "./Archive";
4
+ export * from "./Decompressor";
5
+ export * from "./Protocol";
@@ -0,0 +1,18 @@
1
+ import { Decompressor } from "./Decompressor";
2
+ import { ArchiveHandler } from "./Archive";
3
+
4
+ export type Processors = {
5
+ decompressors: Array<Decompressor>;
6
+ archiveHandler: ArchiveHandler;
7
+ };
8
+
9
+ export type ProcessHandlers = {
10
+ onProgress?: (progress: number, total?: number) => void;
11
+ abortSignal: AbortSignal;
12
+ getProcessors: (pathname: string) => Processors;
13
+ };
14
+
15
+ export type FileSignature = {
16
+ offset: number;
17
+ bytes: number[];
18
+ };
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./download";
3
+ export * from "./unstrusted-script";
4
+ export * from "./piece-selection-sort";
@@ -0,0 +1,34 @@
1
+
2
+ import { RosterLockV1Config } from "../../lock";
3
+ import { PieceType, PlayerId, LogicId } from "../../shared";
4
+ import { UserSelection } from "../../request";
5
+
6
+ export type SortPiecesArg = {
7
+ lockConfig: RosterLockV1Config,
8
+ pieceType: PieceType,
9
+ dataDir: string,
10
+ };
11
+
12
+ export type HandleFullSelectionArg = {
13
+ lockConfig: RosterLockV1Config,
14
+ // In case we only want to save local selections
15
+ localUsers: Array<PlayerId>,
16
+ // User Selections have all users
17
+ userSelections: Record<PlayerId, UserSelection>,
18
+ dataDir: string,
19
+ };
20
+
21
+ export type HandleGameCompleteArg = HandleFullSelectionArg & {
22
+ winners: Array<PlayerId>,
23
+ };
24
+
25
+ export type PieceSelectionSortPlugin = {
26
+ name: string,
27
+ publicInfo: {
28
+ title: string,
29
+ description: string,
30
+ },
31
+ sortPieces: (arg: SortPiecesArg) => Promise<Array<LogicId>>,
32
+ handleFullSelection: (arg: HandleFullSelectionArg) => Promise<void>,
33
+ handleGameComplete: (arg: HandleGameCompleteArg) => Promise<void>,
34
+ };
@@ -0,0 +1,59 @@
1
+ import { RosterLockV1Config, UntrustedScriptRef } from "../../lock";
2
+ import { ScriptPurposeInput } from "./purpose-input";
3
+ export * from "./purpose-input";
4
+
5
+ export type ScriptStarter = {
6
+ config: RosterLockV1Config,
7
+ randomSeeds: string[],
8
+ purpose: ScriptPurposeInput,
9
+ entryScript: UntrustedScriptRef
10
+ debugLog?: Array<string>,
11
+ };
12
+
13
+
14
+ export type ScriptGlobals<ScriptModule> = {
15
+ randomFloat: ()=>number,
16
+ randomInt: (min: number, max: number)=>number,
17
+ shuffleIndexes: (length: number, startOffset?: number)=>Array<number>,
18
+ getPieceMeta: (pieceType: string, pieceId: string)=>any,
19
+ getAvailablePieces: (pieceType: string)=>Array<string>,
20
+ requireScript: (path: string, runCode: (newPath: string, content: string)=>Promise<ScriptModule>)=>Promise<ScriptModule>,
21
+ log: (...args: any)=>void
22
+ };
23
+
24
+
25
+ export type ScriptRunner<ScriptModule> = (
26
+ globals: ScriptGlobals<ScriptModule>,
27
+ input: ScriptPurposeInput,
28
+ script: string,
29
+ initialMethod: string
30
+ )=>Promise<unknown>;
31
+
32
+ export type UntrustedScript<ScriptModule> = {
33
+ name: string,
34
+ extensions: Array<string>,
35
+ directoryFile: Array<string>,
36
+ runScript: ScriptRunner<ScriptModule>,
37
+ exportConfig: (config: any)=>ScriptModule
38
+ };
39
+
40
+ export type UntrustedConfig = {
41
+ name: string,
42
+ extensions: Array<string>,
43
+ runConfig: (configString: string)=>Promise<unknown>
44
+ };
45
+
46
+ export type ScriptStackFrame = {
47
+ filename: string | null,
48
+ line: number | null,
49
+ name: string | null,
50
+ };
51
+
52
+ export type NormalizedScriptError = {
53
+ type: "UntrustedScriptError"
54
+ message: string,
55
+ filename: string | null,
56
+ line: number | null,
57
+ column: number | null,
58
+ stack: ScriptStackFrame[] | null,
59
+ };
@@ -0,0 +1,34 @@
1
+
2
+ import { PlayerId, PieceType } from "../../shared";
3
+ import { SelectedPiece } from "../../request";
4
+
5
+ export type PieceUserValidationInput = {
6
+ type: "piece-user-validation",
7
+ pieceType: string,
8
+ userId: string,
9
+ input: Array<SelectedPiece>,
10
+ };
11
+
12
+ export type PieceMergeInput = {
13
+ type: "piece-merge",
14
+ pieceType: string,
15
+ users: Array<PlayerId>,
16
+ input: Record<PlayerId, Array<SelectedPiece>>,
17
+ };
18
+
19
+ export type GlobalValidationInput = {
20
+ type: "global-validation",
21
+ pieceTypes: Array<string>,
22
+ users: Array<PlayerId>,
23
+ input: Record<PieceType, (
24
+ | Record<PlayerId, Array<SelectedPiece>>
25
+ | Array<SelectedPiece>
26
+ )> ,
27
+ };
28
+
29
+
30
+ export type ScriptPurposeInput = (
31
+ | PieceUserValidationInput
32
+ | PieceMergeInput
33
+ | GlobalValidationInput
34
+ );
@@ -0,0 +1,14 @@
1
+
2
+ export type PlayerId = string;
3
+ export type PieceType = string;
4
+ export type PieceId = string;
5
+ // RosterLockPiece["version"]["logic"] - the piece's real identity. A media/docs
6
+ // update keeps the same LogicId; a logic update is a wholly new one.
7
+ export type LogicId = string;
8
+ export type Sha256 = string;
9
+
10
+ export type RosterLockIdentity<P extends string, V extends number> = {
11
+ namespace: "roster-lock", purpose: P, version: V
12
+ };
13
+
14
+ export type Count = number | "*" | [number, number | "*"];
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "nodenext",
5
+ "moduleResolution": "nodenext",
6
+ "types": [],
7
+ "lib": ["es2022", "dom"],
8
+ "sourceMap": true,
9
+ "rootDir": "./src",
10
+ "outDir": "./dist",
11
+ "esModuleInterop": true,
12
+ "strict": true,
13
+ "skipLibCheck": true,
14
+ "removeComments": true,
15
+ "noImplicitAny": true
16
+ },
17
+ "files": ["src/index.ts"],
18
+ "include": ["./typings", "./types", "**/*.test.ts"],
19
+ "exclude": ["node_modules", "**/*.spec.ts"]
20
+ }