@roster-lock/shared 0.1.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 (314) hide show
  1. package/LICENSE.md +11 -0
  2. package/dist/index.js +19 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/match-lock-file/config-types.js +3 -0
  5. package/dist/match-lock-file/config-types.js.map +1 -0
  6. package/dist/match-lock-file/index.js +19 -0
  7. package/dist/match-lock-file/index.js.map +1 -0
  8. package/dist/match-lock-file/match-config/index.js +18 -0
  9. package/dist/match-lock-file/match-config/index.js.map +1 -0
  10. package/dist/match-lock-file/match-config/version-1/draft/index.js +44 -0
  11. package/dist/match-lock-file/match-config/version-1/draft/index.js.map +1 -0
  12. package/dist/match-lock-file/match-config/version-1/draft/roster-piece-info.js +32 -0
  13. package/dist/match-lock-file/match-config/version-1/draft/roster-piece-info.js.map +1 -0
  14. package/dist/match-lock-file/match-config/version-1/draft/selection-script-info.js +13 -0
  15. package/dist/match-lock-file/match-config/version-1/draft/selection-script-info.js.map +1 -0
  16. package/dist/match-lock-file/match-config/version-1/index.js +22 -0
  17. package/dist/match-lock-file/match-config/version-1/index.js.map +1 -0
  18. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.js +37 -0
  19. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.js.map +1 -0
  20. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.js +43 -0
  21. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.js.map +1 -0
  22. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.js +7 -0
  23. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.js.map +1 -0
  24. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.js +41 -0
  25. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.js.map +1 -0
  26. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.js +20 -0
  27. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.js.map +1 -0
  28. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.js +31 -0
  29. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.js.map +1 -0
  30. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.js +40 -0
  31. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.js.map +1 -0
  32. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.js +17 -0
  33. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.js.map +1 -0
  34. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.js +16 -0
  35. package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.js.map +1 -0
  36. package/dist/match-lock-file/match-config/version-1/lock/engine/index.js +19 -0
  37. package/dist/match-lock-file/match-config/version-1/lock/engine/index.js.map +1 -0
  38. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/error.js +25 -0
  39. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/error.js.map +1 -0
  40. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/index.js +33 -0
  41. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/index.js.map +1 -0
  42. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.js +31 -0
  43. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.js.map +1 -0
  44. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.js +37 -0
  45. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.js.map +1 -0
  46. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.js +22 -0
  47. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.js.map +1 -0
  48. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.js +24 -0
  49. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.js.map +1 -0
  50. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.js +39 -0
  51. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.js.map +1 -0
  52. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.js +46 -0
  53. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.js.map +1 -0
  54. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.js +23 -0
  55. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.js.map +1 -0
  56. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.js +99 -0
  57. package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.js.map +1 -0
  58. package/dist/match-lock-file/match-config/version-1/lock/index.js +56 -0
  59. package/dist/match-lock-file/match-config/version-1/lock/index.js.map +1 -0
  60. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.js +87 -0
  61. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.js.map +1 -0
  62. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/index.js +19 -0
  63. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/index.js.map +1 -0
  64. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.js +94 -0
  65. package/dist/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.js.map +1 -0
  66. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.js +18 -0
  67. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.js.map +1 -0
  68. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.js +28 -0
  69. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.js.map +1 -0
  70. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.js +31 -0
  71. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.js.map +1 -0
  72. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.js +68 -0
  73. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.js.map +1 -0
  74. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.js +49 -0
  75. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.js.map +1 -0
  76. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.js +62 -0
  77. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.js.map +1 -0
  78. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.js +21 -0
  79. package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.js.map +1 -0
  80. package/dist/match-lock-file/match-config/version-1/lock/rosters/index.js +19 -0
  81. package/dist/match-lock-file/match-config/version-1/lock/rosters/index.js.map +1 -0
  82. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.js +10 -0
  83. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.js.map +1 -0
  84. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/human.js +27 -0
  85. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/human.js.map +1 -0
  86. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/id.js +27 -0
  87. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/id.js.map +1 -0
  88. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/index.js +74 -0
  89. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/index.js.map +1 -0
  90. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.js +31 -0
  91. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.js.map +1 -0
  92. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.js +25 -0
  93. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.js.map +1 -0
  94. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/utils.js +23 -0
  95. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/utils.js.map +1 -0
  96. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/version.js +19 -0
  97. package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/version.js.map +1 -0
  98. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.js +42 -0
  99. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.js.map +1 -0
  100. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.js +46 -0
  101. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.js.map +1 -0
  102. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.js +12 -0
  103. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.js.map +1 -0
  104. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.js +49 -0
  105. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.js.map +1 -0
  106. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.js +32 -0
  107. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.js.map +1 -0
  108. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.js +12 -0
  109. package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.js.map +1 -0
  110. package/dist/match-lock-file/match-config/version-1/lock/selection/index.js +19 -0
  111. package/dist/match-lock-file/match-config/version-1/lock/selection/index.js.map +1 -0
  112. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/index.js +33 -0
  113. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/index.js.map +1 -0
  114. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/script.js +23 -0
  115. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/script.js.map +1 -0
  116. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.js +49 -0
  117. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.js.map +1 -0
  118. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.js +14 -0
  119. package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.js.map +1 -0
  120. package/dist/match-lock-file/match-config/version-1/piece-info/file-paths.js +5 -0
  121. package/dist/match-lock-file/match-config/version-1/piece-info/file-paths.js.map +1 -0
  122. package/dist/match-lock-file/match-config/version-1/piece-info/index.js +23 -0
  123. package/dist/match-lock-file/match-config/version-1/piece-info/index.js.map +1 -0
  124. package/dist/match-lock-file/match-config/version-1/piece-info/keywords.js +29 -0
  125. package/dist/match-lock-file/match-config/version-1/piece-info/keywords.js.map +1 -0
  126. package/dist/match-lock-file/match-config/version-1/piece-info/schema.js +19 -0
  127. package/dist/match-lock-file/match-config/version-1/piece-info/schema.js.map +1 -0
  128. package/dist/match-lock-file/match-config/version-1/shared/Identity.js +15 -0
  129. package/dist/match-lock-file/match-config/version-1/shared/Identity.js.map +1 -0
  130. package/dist/match-lock-file/match-config/version-1/shared/SelectedPiece.js +38 -0
  131. package/dist/match-lock-file/match-config/version-1/shared/SelectedPiece.js.map +1 -0
  132. package/dist/match-lock-file/match-config/version-1/shared/count.js +48 -0
  133. package/dist/match-lock-file/match-config/version-1/shared/count.js.map +1 -0
  134. package/dist/match-lock-file/match-config/version-1/shared/index.js +25 -0
  135. package/dist/match-lock-file/match-config/version-1/shared/index.js.map +1 -0
  136. package/dist/match-lock-file/match-config/version-1/usage/calculatePieceVersion.js +70 -0
  137. package/dist/match-lock-file/match-config/version-1/usage/calculatePieceVersion.js.map +1 -0
  138. package/dist/match-lock-file/match-config/version-1/usage/empty-configs.js +49 -0
  139. package/dist/match-lock-file/match-config/version-1/usage/empty-configs.js.map +1 -0
  140. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/constants.js +8 -0
  141. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/constants.js.map +1 -0
  142. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.js +75 -0
  143. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.js.map +1 -0
  144. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.js +28 -0
  145. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.js.map +1 -0
  146. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/index.js +20 -0
  147. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/index.js.map +1 -0
  148. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/types.js +3 -0
  149. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/types.js.map +1 -0
  150. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.js +33 -0
  151. package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.js.map +1 -0
  152. package/dist/match-lock-file/match-config/version-1/usage/index.js +22 -0
  153. package/dist/match-lock-file/match-config/version-1/usage/index.js.map +1 -0
  154. package/dist/match-lock-file/match-config/version-1/usage/publish/SemVer.js +63 -0
  155. package/dist/match-lock-file/match-config/version-1/usage/publish/SemVer.js.map +1 -0
  156. package/dist/match-lock-file/match-config/version-1/usage/publish/diffLocks.js +51 -0
  157. package/dist/match-lock-file/match-config/version-1/usage/publish/diffLocks.js.map +1 -0
  158. package/dist/match-lock-file/match-config/version-1/usage/publish/index.js +19 -0
  159. package/dist/match-lock-file/match-config/version-1/usage/publish/index.js.map +1 -0
  160. package/dist/match-lock-file/match-config/version-1/usage/validate-select/constants.js +14 -0
  161. package/dist/match-lock-file/match-config/version-1/usage/validate-select/constants.js.map +1 -0
  162. package/dist/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.js +53 -0
  163. package/dist/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.js.map +1 -0
  164. package/dist/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.js +49 -0
  165. package/dist/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.js.map +1 -0
  166. package/dist/match-lock-file/match-config/version-1/usage/validate-select/index.js +68 -0
  167. package/dist/match-lock-file/match-config/version-1/usage/validate-select/index.js.map +1 -0
  168. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.js +38 -0
  169. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.js.map +1 -0
  170. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.js +40 -0
  171. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.js.map +1 -0
  172. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.js +78 -0
  173. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.js.map +1 -0
  174. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.js +43 -0
  175. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.js.map +1 -0
  176. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.js +26 -0
  177. package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.js.map +1 -0
  178. package/dist/match-lock-file/util-types/json-schema/JSONSchemaCaster.js +45 -0
  179. package/dist/match-lock-file/util-types/json-schema/JSONSchemaCaster.js.map +1 -0
  180. package/dist/match-lock-file/util-types/json-schema/defineKeyword.js +30 -0
  181. package/dist/match-lock-file/util-types/json-schema/defineKeyword.js.map +1 -0
  182. package/dist/match-lock-file/util-types/json-schema/index.js +21 -0
  183. package/dist/match-lock-file/util-types/json-schema/index.js.map +1 -0
  184. package/dist/match-lock-file/util-types/json-schema/safe-keyword.js +3 -0
  185. package/dist/match-lock-file/util-types/json-schema/safe-keyword.js.map +1 -0
  186. package/dist/match-lock-file/util-types/json-schema/schema-types.js +3 -0
  187. package/dist/match-lock-file/util-types/json-schema/schema-types.js.map +1 -0
  188. package/package.json +49 -0
  189. package/src/index.ts +3 -0
  190. package/src/match-lock-file/config-types.ts +10 -0
  191. package/src/match-lock-file/index.ts +4 -0
  192. package/src/match-lock-file/match-config/index.ts +2 -0
  193. package/src/match-lock-file/match-config/version-0/pieces/caster-runtypes/index.ts +99 -0
  194. package/src/match-lock-file/match-config/version-0/pieces/caster-runtypes/util-casters.ts +155 -0
  195. package/src/match-lock-file/match-config/version-0/pieces/index.ts +3 -0
  196. package/src/match-lock-file/match-config/version-0/pieces/types.ts +49 -0
  197. package/src/match-lock-file/match-config/version-0/pieces/validate/definition/assetCount.ts +33 -0
  198. package/src/match-lock-file/match-config/version-0/pieces/validate/definition/assetType.ts +22 -0
  199. package/src/match-lock-file/match-config/version-0/pieces/validate/definition/index.ts +30 -0
  200. package/src/match-lock-file/match-config/version-0/pieces/validate/definition/pathVariables.ts +39 -0
  201. package/src/match-lock-file/match-config/version-0/pieces/validate/index.ts +4 -0
  202. package/src/match-lock-file/match-config/version-0/pieces/validate/sha.ts +23 -0
  203. package/src/match-lock-file/match-config/version-0/pieces/validate/version.ts +66 -0
  204. package/src/match-lock-file/match-config/version-0/restriction/casters.ts +52 -0
  205. package/src/match-lock-file/match-config/version-0/restriction/index.ts +4 -0
  206. package/src/match-lock-file/match-config/version-0/restriction/types.ts +42 -0
  207. package/src/match-lock-file/match-config/version-0/restriction/validate/index.ts +15 -0
  208. package/src/match-lock-file/match-config/version-0/restriction/validate/piece/index.ts +46 -0
  209. package/src/match-lock-file/match-config/version-0/restriction/validate/sha.ts +19 -0
  210. package/src/match-lock-file/match-config/version-0/selection/casters.ts +105 -0
  211. package/src/match-lock-file/match-config/version-0/selection/validate/count.ts +16 -0
  212. package/src/match-lock-file/match-config/version-0/selection/validate/index.ts +40 -0
  213. package/src/match-lock-file/match-config/version-0/selection/validate/scriptMeta.ts +26 -0
  214. package/src/match-lock-file/match-config/version-1/draft/index.ts +52 -0
  215. package/src/match-lock-file/match-config/version-1/draft/roster-piece-info.ts +33 -0
  216. package/src/match-lock-file/match-config/version-1/draft/selection-script-info.ts +16 -0
  217. package/src/match-lock-file/match-config/version-1/index.ts +7 -0
  218. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.ts +46 -0
  219. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.ts +48 -0
  220. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.ts +6 -0
  221. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.ts +42 -0
  222. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.ts +26 -0
  223. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.ts +34 -0
  224. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.ts +47 -0
  225. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.ts +22 -0
  226. package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.ts +14 -0
  227. package/src/match-lock-file/match-config/version-1/lock/engine/index.ts +3 -0
  228. package/src/match-lock-file/match-config/version-1/lock/engine/validate/constants.ts +7 -0
  229. package/src/match-lock-file/match-config/version-1/lock/engine/validate/error.ts +21 -0
  230. package/src/match-lock-file/match-config/version-1/lock/engine/validate/index.ts +18 -0
  231. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.ts +41 -0
  232. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.ts +55 -0
  233. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.ts +21 -0
  234. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.ts +28 -0
  235. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.ts +46 -0
  236. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.ts +37 -0
  237. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.ts +21 -0
  238. package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.ts +117 -0
  239. package/src/match-lock-file/match-config/version-1/lock/index.ts +51 -0
  240. package/src/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.ts +97 -0
  241. package/src/match-lock-file/match-config/version-1/lock/piece-meta/index.ts +3 -0
  242. package/src/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.ts +114 -0
  243. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.ts +25 -0
  244. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.ts +33 -0
  245. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.ts +33 -0
  246. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.ts +103 -0
  247. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.ts +59 -0
  248. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.ts +71 -0
  249. package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.ts +22 -0
  250. package/src/match-lock-file/match-config/version-1/lock/rosters/index.ts +3 -0
  251. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.ts +9 -0
  252. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/human.ts +22 -0
  253. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/id.ts +20 -0
  254. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/index.ts +83 -0
  255. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.ts +40 -0
  256. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.ts +30 -0
  257. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/utils.ts +17 -0
  258. package/src/match-lock-file/match-config/version-1/lock/rosters/validate/version.ts +22 -0
  259. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.ts +53 -0
  260. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.ts +54 -0
  261. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.ts +11 -0
  262. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.ts +58 -0
  263. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.ts +37 -0
  264. package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.ts +11 -0
  265. package/src/match-lock-file/match-config/version-1/lock/selection/index.ts +3 -0
  266. package/src/match-lock-file/match-config/version-1/lock/selection/validate/index.ts +37 -0
  267. package/src/match-lock-file/match-config/version-1/lock/selection/validate/script.ts +28 -0
  268. package/src/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.ts +69 -0
  269. package/src/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.ts +18 -0
  270. package/src/match-lock-file/match-config/version-1/piece-info/file-paths.ts +2 -0
  271. package/src/match-lock-file/match-config/version-1/piece-info/index.ts +14 -0
  272. package/src/match-lock-file/match-config/version-1/piece-info/keywords.ts +39 -0
  273. package/src/match-lock-file/match-config/version-1/piece-info/schema.ts +29 -0
  274. package/src/match-lock-file/match-config/version-1/shared/Identity.ts +14 -0
  275. package/src/match-lock-file/match-config/version-1/shared/SelectedPiece.ts +49 -0
  276. package/src/match-lock-file/match-config/version-1/shared/count.ts +47 -0
  277. package/src/match-lock-file/match-config/version-1/shared/index.ts +9 -0
  278. package/src/match-lock-file/match-config/version-1/usage/calculatePieceVersion.ts +85 -0
  279. package/src/match-lock-file/match-config/version-1/usage/empty-configs.ts +61 -0
  280. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/constants.ts +6 -0
  281. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.ts +88 -0
  282. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.ts +42 -0
  283. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/index.ts +4 -0
  284. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/types.ts +5 -0
  285. package/src/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.ts +34 -0
  286. package/src/match-lock-file/match-config/version-1/usage/index.ts +6 -0
  287. package/src/match-lock-file/match-config/version-1/usage/publish/SemVer.ts +67 -0
  288. package/src/match-lock-file/match-config/version-1/usage/publish/diffLocks.ts +66 -0
  289. package/src/match-lock-file/match-config/version-1/usage/publish/index.ts +2 -0
  290. package/src/match-lock-file/match-config/version-1/usage/validate-select/constants.ts +9 -0
  291. package/src/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.ts +61 -0
  292. package/src/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.ts +54 -0
  293. package/src/match-lock-file/match-config/version-1/usage/validate-select/index.ts +98 -0
  294. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.ts +49 -0
  295. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.ts +39 -0
  296. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/include-mandatory-require.ts +44 -0
  297. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.ts +101 -0
  298. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.ts +51 -0
  299. package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.ts +36 -0
  300. package/src/match-lock-file/util-types/json-schema/JSONSchemaCaster.ts +52 -0
  301. package/src/match-lock-file/util-types/json-schema/checkVersion.ts +9 -0
  302. package/src/match-lock-file/util-types/json-schema/defineKeyword.ts +50 -0
  303. package/src/match-lock-file/util-types/json-schema/index.ts +4 -0
  304. package/src/match-lock-file/util-types/json-schema/safe-keyword.ts +27 -0
  305. package/src/match-lock-file/util-types/json-schema/schema-types.ts +5 -0
  306. package/tests/engine/assets.spec.ts +147 -0
  307. package/tests/engine/official-selections.spec.ts +67 -0
  308. package/tests/engine/requirements.spec.ts +43 -0
  309. package/tests/piece-info/cast.spec.ts +20 -0
  310. package/tests/piece-info/rosterlock.piece-info.json +15 -0
  311. package/tests/piece-meta/cast.spec.ts +60 -0
  312. package/tests/rosters/path-variables.spec.ts +52 -0
  313. package/tests/selection/cast-result.spec.ts +72 -0
  314. package/tsconfig.json +20 -0
@@ -0,0 +1,147 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+ import { RosterLockV1Config } from "@roster-lock/types";
4
+
5
+ import { ROSTERLOCK_V1_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/lock/index.js";
6
+ import { EMPTY_ROSTER_LOCK } from "../../src/match-lock-file/match-config/version-1/usage/empty-configs.js";
7
+ import { getMatchingAssetsForFile } from "../../src/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.js";
8
+ import { PieceDefinition } from "../../src/match-lock-file/match-config/version-1/usage/files-and-assets/types.js";
9
+
10
+ function buildLockWithAssetPiece(): RosterLockV1Config {
11
+ const lock = cloneJSON(EMPTY_ROSTER_LOCK);
12
+ lock.engine.pieceDefinitions["character"] = {
13
+ selectionStrategy: "mandatory",
14
+ requires: [],
15
+ pathVariables: ["skin"],
16
+ assets: [{ name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] }],
17
+ };
18
+ lock.rosters["character"] = [];
19
+ return lock;
20
+ }
21
+
22
+ describe("engine piece assets validation", () => {
23
+ it("accepts a piece whose asset names are unique and globs use declared path variables", () => {
24
+ const lock = buildLockWithAssetPiece();
25
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
26
+ });
27
+
28
+ it("rejects a piece with a duplicate asset name", () => {
29
+ const lock = buildLockWithAssetPiece();
30
+ lock.engine.pieceDefinitions["character"].assets.push(
31
+ { name: "sprite", classification: "media", count: 1, glob: ["other/*.png"] }
32
+ );
33
+
34
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
35
+ expect(result.valid).toBe(false);
36
+ if(result.valid) return;
37
+ expect(result.error.some((e) => /duplicate name/i.test(e.message ?? ""))).toBe(true);
38
+ });
39
+
40
+ it("rejects an asset glob referencing a path variable the piece type doesn't declare", () => {
41
+ const lock = buildLockWithAssetPiece();
42
+ lock.engine.pieceDefinitions["character"].assets[0].glob = ["<region>/*.png"];
43
+
44
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
45
+ expect(result.valid).toBe(false);
46
+ if(result.valid) return;
47
+ expect(result.error.some((e) => /undefined path variable/i.test(e.message ?? ""))).toBe(true);
48
+ });
49
+ });
50
+
51
+ function buildPieceDefinition(
52
+ pathVariables: PieceDefinition["pathVariables"],
53
+ assets: PieceDefinition["assets"],
54
+ ): PieceDefinition {
55
+ return { selectionStrategy: "mandatory", requires: [], pathVariables, assets };
56
+ }
57
+
58
+ describe("getMatchingAssetsForFile path variables and globs", () => {
59
+ it("matches a glob once its path variable is substituted with the roster's value", () => {
60
+ const piece = buildPieceDefinition(["skin"], [
61
+ { name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] },
62
+ ]);
63
+ const matches = getMatchingAssetsForFile(piece, { skin: "blue" }, "blue/idle.png");
64
+ expect(matches.map((a) => a.name)).toEqual(["sprite"]);
65
+ });
66
+
67
+ it("does not match when the file's path segment differs from the path variable's value", () => {
68
+ const piece = buildPieceDefinition(["skin"], [
69
+ { name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] },
70
+ ]);
71
+ expect(getMatchingAssetsForFile(piece, { skin: "blue" }, "red/idle.png")).toEqual([]);
72
+ });
73
+
74
+ it("matches a path variable used inside a filename, not just a directory segment", () => {
75
+ // Ikemen-Go style character defs, e.g. "<character>.def"
76
+ const piece = buildPieceDefinition(["character"], [
77
+ { name: "def-file", classification: "logic", count: 1, glob: ["<character>.def"] },
78
+ ]);
79
+ expect(getMatchingAssetsForFile(piece, { character: "kfm" }, "kfm.def").map((a) => a.name))
80
+ .toEqual(["def-file"]);
81
+ expect(getMatchingAssetsForFile(piece, { character: "kfm" }, "ryu.def")).toEqual([]);
82
+ });
83
+
84
+ it("resolves multiple path variables combined with a globstar across nested directories", () => {
85
+ const piece = buildPieceDefinition(["character", "skin"], [
86
+ { name: "sprite", classification: "media", count: 1, glob: ["<character>/<skin>/**/*.png"] },
87
+ ]);
88
+ const pathVariables = { character: "kfm", skin: "default" };
89
+ expect(getMatchingAssetsForFile(piece, pathVariables, "kfm/default/stance/1.png").length).toBe(1);
90
+ expect(getMatchingAssetsForFile(piece, pathVariables, "kfm/other/stance/1.png")).toEqual([]);
91
+ expect(getMatchingAssetsForFile(piece, pathVariables, "other/default/stance/1.png")).toEqual([]);
92
+ });
93
+
94
+ it("matches an asset if any of its globs match, mixing a literal glob with a path-variable glob", () => {
95
+ const piece = buildPieceDefinition(["skin"], [
96
+ { name: "sprite", classification: "media", count: 1, glob: ["portrait.png", "<skin>/*.png"] },
97
+ ]);
98
+ expect(getMatchingAssetsForFile(piece, { skin: "blue" }, "portrait.png").map((a) => a.name))
99
+ .toEqual(["sprite"]);
100
+ expect(getMatchingAssetsForFile(piece, { skin: "blue" }, "blue/idle.png").map((a) => a.name))
101
+ .toEqual(["sprite"]);
102
+ expect(getMatchingAssetsForFile(piece, { skin: "blue" }, "red/idle.png")).toEqual([]);
103
+ });
104
+
105
+ it("matches via exact equality when the glob has no wildcard characters", () => {
106
+ const piece = buildPieceDefinition([], [
107
+ { name: "portrait", classification: "media", count: 1, glob: ["assets/portrait.png"] },
108
+ ]);
109
+ expect(getMatchingAssetsForFile(piece, {}, "assets/portrait.png").map((a) => a.name))
110
+ .toEqual(["portrait"]);
111
+ });
112
+
113
+ it("allows path variable values containing spaces", () => {
114
+ const piece = buildPieceDefinition(["skin"], [
115
+ { name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] },
116
+ ]);
117
+ expect(getMatchingAssetsForFile(piece, { skin: "light blue" }, "light blue/idle.png").map((a) => a.name))
118
+ .toEqual(["sprite"]);
119
+ });
120
+
121
+ it("returns every asset whose glob matches, when globs overlap", () => {
122
+ const piece = buildPieceDefinition(["skin"], [
123
+ { name: "any-png", classification: "media", count: 1, glob: ["<skin>/*.png"] },
124
+ { name: "idle-png", classification: "media", count: 1, glob: ["<skin>/idle.png"] },
125
+ ]);
126
+ const matches = getMatchingAssetsForFile(piece, { skin: "blue" }, "blue/idle.png");
127
+ expect(matches.map((a) => a.name).sort()).toEqual(["any-png", "idle-png"]);
128
+ });
129
+
130
+ it("throws instead of matching when a path variable value contains disallowed characters", () => {
131
+ // Guards against path variable values being used to smuggle glob/traversal syntax into the pattern
132
+ const piece = buildPieceDefinition(["skin"], [
133
+ { name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] },
134
+ ]);
135
+ expect(() => getMatchingAssetsForFile(piece, { skin: "../etc" }, "../etc/idle.png"))
136
+ .toThrow(/invalid characters/i);
137
+ expect(() => getMatchingAssetsForFile(piece, { skin: "*" }, "*/idle.png"))
138
+ .toThrow(/invalid characters/i);
139
+ });
140
+
141
+ it("throws when a path variable value is empty", () => {
142
+ const piece = buildPieceDefinition(["skin"], [
143
+ { name: "sprite", classification: "media", count: 1, glob: ["<skin>/*.png"] },
144
+ ]);
145
+ expect(() => getMatchingAssetsForFile(piece, { skin: "" }, "idle.png")).toThrow(/too short/i);
146
+ });
147
+ });
@@ -0,0 +1,67 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+ import { RosterLockV1Config } from "@roster-lock/types";
4
+
5
+ import { ROSTERLOCK_V1_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/lock/index.js";
6
+ import { EMPTY_ROSTER_LOCK } from "../../src/match-lock-file/match-config/version-1/usage/empty-configs.js";
7
+
8
+ function buildLock(): RosterLockV1Config {
9
+ return cloneJSON(EMPTY_ROSTER_LOCK);
10
+ }
11
+
12
+ describe("engine officialSelections validation", () => {
13
+ it("is optional - a lock with no officialSelections is still valid", () => {
14
+ const lock = buildLock();
15
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
16
+ });
17
+
18
+ it("accepts a list of tagged, unique, well-formed hashes", () => {
19
+ const lock = buildLock();
20
+ lock.engine.officialSelections = [
21
+ { tag: "3v3-tag-team", hash: "a".repeat(64) },
22
+ { tag: "1v1", hash: "b".repeat(64) },
23
+ ];
24
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
25
+ });
26
+
27
+ it("rejects a hash that isn't a 64-char hex string", () => {
28
+ const lock = buildLock();
29
+ lock.engine.officialSelections = [{ tag: "1v1", hash: "not-a-hash" }];
30
+
31
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
32
+ expect(result.valid).toBe(false);
33
+ if(result.valid) return;
34
+ expect(result.error.some((e) => /not a valid SHA-256/i.test(e.message ?? ""))).toBe(true);
35
+ });
36
+
37
+ it("rejects two entries sharing the same hash, even under different tags", () => {
38
+ const lock = buildLock();
39
+ const hash = "a".repeat(64);
40
+ lock.engine.officialSelections = [
41
+ { tag: "3v3-tag-team", hash },
42
+ { tag: "3v3-tag-team-v2", hash },
43
+ ];
44
+
45
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
46
+ expect(result.valid).toBe(false);
47
+ if(result.valid) return;
48
+ expect(result.error.some((e) => /duplicate official selection hash/i.test(e.message ?? ""))).toBe(true);
49
+ });
50
+
51
+ it("allows two entries sharing the same tag with different hashes (a revision under the same UI screen)", () => {
52
+ const lock = buildLock();
53
+ lock.engine.officialSelections = [
54
+ { tag: "3v3-tag-team", hash: "a".repeat(64) },
55
+ { tag: "3v3-tag-team", hash: "b".repeat(64) },
56
+ ];
57
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
58
+ });
59
+
60
+ it("rejects an entry missing a tag", () => {
61
+ const lock = buildLock();
62
+ lock.engine.officialSelections = [{ hash: "a".repeat(64) } as any];
63
+
64
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
65
+ expect(result.valid).toBe(false);
66
+ });
67
+ });
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+ import { RosterLockV1Config } from "@roster-lock/types";
4
+
5
+ import { ROSTERLOCK_V1_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/lock/index.js";
6
+ import { EMPTY_ROSTER_LOCK } from "../../src/match-lock-file/match-config/version-1/usage/empty-configs.js";
7
+
8
+ function buildLockWithRequiresPiece(): RosterLockV1Config {
9
+ const lock = cloneJSON(EMPTY_ROSTER_LOCK);
10
+ lock.engine.pieceDefinitions["character"] = {
11
+ selectionStrategy: "mandatory",
12
+ requires: ["hat"],
13
+ pathVariables: [],
14
+ assets: [],
15
+ };
16
+ lock.engine.pieceDefinitions["hat"] = {
17
+ selectionStrategy: "on demand",
18
+ requires: [],
19
+ pathVariables: [],
20
+ assets: [],
21
+ };
22
+ lock.rosters["character"] = [];
23
+ lock.rosters["hat"] = [];
24
+ return lock;
25
+ }
26
+
27
+ describe("engine piece requirements validation", () => {
28
+ it("accepts a piece that requires an on-demand piece with no cycle", () => {
29
+ const lock = buildLockWithRequiresPiece();
30
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
31
+ });
32
+
33
+ it("rejects piece types whose requirements form a cycle", () => {
34
+ const lock = buildLockWithRequiresPiece();
35
+ lock.engine.pieceDefinitions["character"].selectionStrategy = "on demand";
36
+ lock.engine.pieceDefinitions["hat"].requires = ["character"];
37
+
38
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
39
+ expect(result.valid).toBe(false);
40
+ if(result.valid) return;
41
+ expect(result.error.some((e) => /form a cycle/i.test(e.message ?? ""))).toBe(true);
42
+ });
43
+ });
@@ -0,0 +1,20 @@
1
+ import { describe, it, expect } from "vitest";
2
+
3
+ import { ROSTERLOCK_V1_PIECEINFO_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/piece-info/index.js";
4
+
5
+ import pieceInfoJson from "./rosterlock.piece-info.json";
6
+
7
+ describe("ROSTERLOCK_V1_PIECEINFO_CASTER_JSONSCHEMA", () => {
8
+ it("casts a valid piece-info JSON file", () => {
9
+ const result = ROSTERLOCK_V1_PIECEINFO_CASTER_JSONSCHEMA.safeCast(pieceInfoJson);
10
+ expect(result.valid).toBe(true);
11
+ if (!result.valid) return;
12
+ expect(result.value.configIdentity.namespace).toBe("roster-lock");
13
+ expect(result.value.configIdentity.purpose).toBe("piece-info");
14
+ expect(result.value.configIdentity.version).toBe(1);
15
+ expect(result.value.humanInfo.name).toBe("Blue");
16
+ expect(result.value.humanInfo.author).toBe("match-lock");
17
+ expect(result.value.downloadSources).toEqual(["http://localhost:7342/pieces/character/blue.tar"]);
18
+ expect(result.value.pathVariables).toEqual({});
19
+ });
20
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "configIdentity": {
3
+ "namespace": "roster-lock",
4
+ "purpose": "piece-info",
5
+ "version": 1
6
+ },
7
+ "humanInfo": {
8
+ "name": "Blue",
9
+ "author": "match-lock",
10
+ "url": "http://localhost:7342/pieces/character/blue"
11
+ },
12
+ "downloadSources": ["http://localhost:7342/pieces/character/blue.tar"],
13
+ "pathVariables": {}
14
+ }
15
+
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+ import { RosterLockV1Config } from "@roster-lock/types";
4
+
5
+ import { ROSTERLOCK_V1_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/lock/index.js";
6
+ import { EMPTY_ROSTER_LOCK } from "../../src/match-lock-file/match-config/version-1/usage/empty-configs.js";
7
+
8
+ function buildLockWithPieceMeta(): RosterLockV1Config {
9
+ const lock = cloneJSON(EMPTY_ROSTER_LOCK);
10
+ lock.engine.pieceDefinitions["character"] = {
11
+ selectionStrategy: "mandatory",
12
+ requires: [],
13
+ pathVariables: [],
14
+ assets: [],
15
+ };
16
+ lock.rosters["character"] = [{
17
+ id: "@author/blue",
18
+ version: { logic: "a".repeat(64), media: "b".repeat(64), docs: "c".repeat(64) },
19
+ humanInfo: { name: "Blue", author: "author", url: "https://example.com/blue" },
20
+ downloadSources: ["https://example.com/blue.tar"],
21
+ pathVariables: {},
22
+ requiredPieces: {},
23
+ }];
24
+ lock.selection.piece["character"] = {
25
+ type: "unselectable",
26
+ };
27
+ lock.pieceMeta["character"] = {
28
+ schema: { power: "number" },
29
+ defaultMeta: { power: 1 },
30
+ values: { "@author/blue": { power: 5 } },
31
+ };
32
+ return lock;
33
+ }
34
+
35
+ describe("piece meta validation", () => {
36
+ it("accepts default meta and per-piece meta that match the declared schema", () => {
37
+ const lock = buildLockWithPieceMeta();
38
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
39
+ });
40
+
41
+ it("rejects default meta missing a required schema key", () => {
42
+ const lock = buildLockWithPieceMeta();
43
+ lock.pieceMeta["character"].defaultMeta = {};
44
+
45
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
46
+ expect(result.valid).toBe(false);
47
+ if(result.valid) return;
48
+ expect(result.error.some((e) => /must have all required keys/i.test(e.message ?? ""))).toBe(true);
49
+ });
50
+
51
+ it("rejects per-piece meta for a piece that isn't in the roster", () => {
52
+ const lock = buildLockWithPieceMeta();
53
+ lock.pieceMeta["character"].values = { "@author/missing": { power: 2 } };
54
+
55
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
56
+ expect(result.valid).toBe(false);
57
+ if(result.valid) return;
58
+ expect(result.error.some((e) => /not in the roster/i.test(e.message ?? ""))).toBe(true);
59
+ });
60
+ });
@@ -0,0 +1,52 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+ import { RosterLockV1Config } from "@roster-lock/types";
4
+
5
+ import { ROSTERLOCK_V1_CASTER_JSONSCHEMA } from "../../src/match-lock-file/match-config/version-1/lock/index.js";
6
+ import { EMPTY_ROSTER_LOCK } from "../../src/match-lock-file/match-config/version-1/usage/empty-configs.js";
7
+
8
+ function buildLockWithPathVariablePiece(): RosterLockV1Config {
9
+ const lock = cloneJSON(EMPTY_ROSTER_LOCK);
10
+ lock.engine.pieceDefinitions["character"] = {
11
+ selectionStrategy: "mandatory",
12
+ requires: [],
13
+ pathVariables: ["skin"],
14
+ assets: [{ name: "sprite", classification: "media", count: 1, glob: ["{skin}/*.png"] }],
15
+ };
16
+ lock.rosters["character"] = [{
17
+ id: "@author/blue",
18
+ version: { logic: "a".repeat(64), media: "b".repeat(64), docs: "c".repeat(64) },
19
+ humanInfo: { name: "Blue", author: "author", url: "https://example.com/blue" },
20
+ downloadSources: ["https://example.com/blue.tar"],
21
+ pathVariables: { skin: "blue" },
22
+ requiredPieces: {},
23
+ }];
24
+ return lock;
25
+ }
26
+
27
+ describe("roster piece pathVariables validation", () => {
28
+ it("accepts a piece whose pathVariables match the piece type's declared names", () => {
29
+ const lock = buildLockWithPathVariablePiece();
30
+ expect(() => ROSTERLOCK_V1_CASTER_JSONSCHEMA.cast(lock)).not.toThrow();
31
+ });
32
+
33
+ it("rejects a piece missing a required path variable", () => {
34
+ const lock = buildLockWithPathVariablePiece();
35
+ lock.rosters["character"][0].pathVariables = {};
36
+
37
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
38
+ expect(result.valid).toBe(false);
39
+ if(result.valid) return;
40
+ expect(result.error.some((e) => /missing value for path variable/i.test(e.message ?? ""))).toBe(true);
41
+ });
42
+
43
+ it("rejects a piece with a path variable name the piece type doesn't declare", () => {
44
+ const lock = buildLockWithPathVariablePiece();
45
+ lock.rosters["character"][0].pathVariables = { skin: "blue", region: "eu" };
46
+
47
+ const result = ROSTERLOCK_V1_CASTER_JSONSCHEMA.safeCast(lock);
48
+ expect(result.valid).toBe(false);
49
+ if(result.valid) return;
50
+ expect(result.error.some((e) => /does not have path variable/i.test(e.message ?? ""))).toBe(true);
51
+ });
52
+ });
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from "vitest";
2
+
3
+ import { castSharedResult, castPersonalResult } from "../../src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.js";
4
+
5
+ function validPiece() {
6
+ return {
7
+ id: "@author/blue",
8
+ required: {
9
+ character: {
10
+ mandatory: [
11
+ {
12
+ id: "@author/red",
13
+ required: {},
14
+ },
15
+ ],
16
+ selectable: [],
17
+ },
18
+ },
19
+ };
20
+ }
21
+
22
+ describe("castSharedResult", () => {
23
+ it("accepts a SelectedPiece with required keyed by piece type", () => {
24
+ const value = [validPiece()];
25
+ expect(() => castSharedResult(value)).not.toThrow();
26
+ expect(castSharedResult(value)).toEqual(value);
27
+ });
28
+
29
+ it("accepts a piece with no required entries", () => {
30
+ const value = [{ id: "@author/blue", required: {} }];
31
+ expect(() => castSharedResult(value)).not.toThrow();
32
+ });
33
+
34
+ it("rejects required.mandatory/selectable placed directly on the piece instead of under a piece-type key", () => {
35
+ const value = [{
36
+ id: "@author/blue",
37
+ required: { mandatory: [], selectable: [] },
38
+ }];
39
+ expect(() => castSharedResult(value)).toThrow();
40
+ });
41
+
42
+ it("rejects a piece missing an id", () => {
43
+ const value = [{ required: {} }];
44
+ expect(() => castSharedResult(value)).toThrow();
45
+ });
46
+
47
+ it("rejects a piece-type entry missing mandatory/selectable", () => {
48
+ const value = [{
49
+ id: "@author/blue",
50
+ required: { character: { mandatory: [] } },
51
+ }];
52
+ expect(() => castSharedResult(value)).toThrow();
53
+ });
54
+
55
+ it("rejects unknown properties on a piece", () => {
56
+ const value = [{ id: "@author/blue", required: {}, extra: true }];
57
+ expect(() => castSharedResult(value)).toThrow();
58
+ });
59
+ });
60
+
61
+ describe("castPersonalResult", () => {
62
+ it("accepts a map of user id to selected pieces", () => {
63
+ const value = { user1: [validPiece()] };
64
+ expect(() => castPersonalResult(value)).not.toThrow();
65
+ expect(castPersonalResult(value)).toEqual(value);
66
+ });
67
+
68
+ it("rejects a user's selection containing an invalid piece", () => {
69
+ const value = { user1: [{ id: "@author/blue", required: { mandatory: [], selectable: [] } }] };
70
+ expect(() => castPersonalResult(value)).toThrow();
71
+ });
72
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "nodenext",
5
+ "moduleResolution": "nodenext",
6
+ "types": ["node"],
7
+ "lib": ["es2022"],
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
+ }