@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,85 @@
1
+ import { RosterLockV1Config } from "@roster-lock/types";
2
+
3
+ type PieceDefinition = RosterLockV1Config["engine"]["pieceDefinitions"][string];
4
+ type EngineAssetDefinition = PieceDefinition["assets"][number];
5
+
6
+ type FileWithSha = { path: string, asset: EngineAssetDefinition, sha: string }
7
+ type FileGetter = (path: string) => Promise<{ byteSize: number, stream: AsyncIterable<Uint8Array> }>
8
+ type ProgressListener = (progress: { file: string, current: number, total: number }) => any
9
+ export async function calculatePieceVersion(
10
+ files: Map<string, { assets: Array<EngineAssetDefinition> }>,
11
+ getFile: FileGetter,
12
+ onProgress?: ProgressListener
13
+ ){
14
+ const logicFiles: Array<FileWithSha> = [];
15
+ const mediaFiles: Array<FileWithSha> = [];
16
+ const docFiles: Array<FileWithSha> = [];
17
+
18
+ await Promise.all(Array.from(files.entries()).map(async ([relativePath, { assets }]) => {
19
+ const sha = await getHashFromFile(relativePath, getFile, onProgress);
20
+ const asset = assets[0];
21
+ if(!asset) throw new Error(`No asset found for ${relativePath}`);
22
+ switch(asset.classification){
23
+ case "logic": logicFiles.push({ path: relativePath, asset, sha }); break;
24
+ case "media": mediaFiles.push({ path: relativePath, asset, sha }); break;
25
+ case "doc": docFiles.push({ path: relativePath, asset, sha }); break;
26
+ default: throw new Error(`Unknown asset type ${asset.classification}`);
27
+ }
28
+ }));
29
+
30
+ return {
31
+ logic: await calculateComnbinedHash(logicFiles.sort(shaSort)),
32
+ media: await calculateComnbinedHash(mediaFiles.sort(shaSort)),
33
+ docs: await calculateComnbinedHash(docFiles.sort(shaSort)),
34
+ }
35
+ }
36
+
37
+ function shaSort(a: FileWithSha, b: FileWithSha){
38
+ return a.sha.localeCompare(b.sha);
39
+ }
40
+
41
+ async function getHashFromFile(
42
+ file: string, getFile: FileGetter, onProgress?: ProgressListener
43
+ ){
44
+ try {
45
+ const { stream, byteSize } = await getFile(file);
46
+ const buffer = new Uint8Array(byteSize);
47
+ let consumed = 0;
48
+ for await (const chunk of stream){
49
+ buffer.set(chunk, consumed);
50
+ consumed += chunk.byteLength;
51
+ onProgress && onProgress({ file, current: consumed, total: byteSize });
52
+ }
53
+ return toHex(await crypto.subtle.digest("SHA-256", buffer));
54
+ }catch(e){
55
+ throw new Error("Failed to calculate Hash from file")
56
+ }
57
+ }
58
+
59
+
60
+ async function calculateComnbinedHash(files: Array<FileWithSha>){
61
+ if (files.length === 0) {
62
+ return toHex(await crypto.subtle.digest("SHA-256", new Uint8Array(0)));
63
+ }
64
+
65
+ // Create our array with expected length ahead of time
66
+ const buffer = new Uint8Array(files.length * 32);
67
+ let offset = 0;
68
+ for(const { sha } of files){
69
+ for (let i = 0; i < sha.length; i += 2) {
70
+ // For each 2 characters
71
+ // Try to parse those two chararacters as if it were a hex value
72
+ const byte = Number.parseInt(sha.substring(i, i + 2), 16)
73
+ // If parsing failed, we failed
74
+ if(Number.isNaN(byte)) throw new Error(`Invalid SHA: ${sha}`);
75
+ // If we're ok, we set the byte on the offset directly
76
+ buffer[offset++] = byte;
77
+ }
78
+ }
79
+ return toHex(await crypto.subtle.digest("SHA-256", buffer));
80
+ }
81
+
82
+ function toHex(buffer: ArrayBuffer): string {
83
+ return Array.from(new Uint8Array(buffer)).map(b => b.toString(16).padStart(2, "0")).join("");
84
+ }
85
+
@@ -0,0 +1,61 @@
1
+ import { RosterLockV1Config, RosterLockV1Draft } from "@roster-lock/types";
2
+ import { cloneJSON } from "@roster-lock/utils";
3
+
4
+ export const EMPTY_ROSTER_LOCK: RosterLockV1Config = {
5
+ configIdentity: { namespace: "roster-lock", purpose: "lock", version: 1 },
6
+ author: "",
7
+ title: "",
8
+ version: "0.0.0",
9
+ engine: { name: "", version: "", pieceDefinitions: {} },
10
+ rosters: {},
11
+ selection: { piece: {}, globalValidation: [], scriptDictionary: {}, },
12
+ pieceMeta: {},
13
+ }
14
+
15
+ export const EMPTY_ROSTER_DRAFT: RosterLockV1Draft = {
16
+ configIdentity: { namespace: "roster-lock", purpose: "draft", version: 1 },
17
+ previousLock: cloneJSON(EMPTY_ROSTER_LOCK),
18
+ stagedLock: cloneJSON(EMPTY_ROSTER_LOCK),
19
+ draft: {
20
+ rosterPieceInfo: {},
21
+ selectionScriptInfo: {},
22
+ }
23
+ };
24
+
25
+ import {
26
+ SelectionGameControlledConfig,
27
+ SelectionNormalConfig,
28
+ SelectionPreselectedConfig,
29
+ SelectionUnselectableConfig,
30
+ SelectionPieceMeta,
31
+ JSONShallowObject,
32
+ } from "@roster-lock/types";
33
+ export const EMPTY_ROSTER_GAME_SELECTION: SelectionGameControlledConfig = {
34
+ type: "game-controlled",
35
+ }
36
+
37
+ export const EMPTY_ROSTER_NORMAL_SELECTION: SelectionNormalConfig = {
38
+ type: "normal",
39
+ validation: {
40
+ count: "*",
41
+ unique: false,
42
+ banList: [],
43
+ customValidation: []
44
+ },
45
+ mergeAlgorithm: void 0
46
+ }
47
+
48
+ export const EMPTY_ROSTER_PRESELECTED_SELECTION: SelectionPreselectedConfig = {
49
+ type: "preselected",
50
+ pieces: []
51
+ }
52
+
53
+ export const EMPTY_ROSTER_UNSELECTABLE_SELECTION: SelectionUnselectableConfig = {
54
+ type: "unselectable",
55
+ }
56
+
57
+ export const EMPTY_PIECE_META: SelectionPieceMeta<JSONShallowObject> = {
58
+ schema: {},
59
+ defaultMeta: {},
60
+ values: {},
61
+ }
@@ -0,0 +1,6 @@
1
+
2
+ import { PATH_ROSTERLOCK_PIECE_INFO } from "../../piece-info"
3
+
4
+ export const FILES_TO_IGNORE = [
5
+ PATH_ROSTERLOCK_PIECE_INFO
6
+ ];
@@ -0,0 +1,88 @@
1
+ import { FILES_TO_IGNORE } from "./constants";
2
+
3
+ import { getMatchingAssetsForFile } from "./getMatchingAsset";
4
+
5
+ import { PieceDefinition, EngineAssetDefinition } from "./types";
6
+
7
+ export { getMatchingAssetsForFile };
8
+
9
+ export async function getAssetsOfFiles(
10
+ files: Iterable<string> | AsyncIterable<string>,
11
+ pathVariables: Record<string, string>,
12
+ pieceDefinition: PieceDefinition,
13
+ ): Promise<{
14
+ assetsWithFiles: Map<string, { asset: EngineAssetDefinition, files: Array<string> }>
15
+ filesWithAssets: Map<string, { assets: Array<EngineAssetDefinition> }>
16
+ }>{
17
+ const assetCounts = new Map<string, { files: Array<string>, asset: EngineAssetDefinition }>();
18
+ const fileCounts = new Map<string, { assets: Array<EngineAssetDefinition> }>();
19
+ for await (const filePath of files){
20
+ if(FILES_TO_IGNORE.includes(filePath)) continue;
21
+
22
+ const assetMatching = getMatchingAssetsForFile(pieceDefinition, pathVariables, filePath);
23
+ const asset = assetMatching[0];
24
+ if(!asset){
25
+ // Error: File doesn't match any assets
26
+ fileCounts.set(filePath, { assets: [] });
27
+ continue;
28
+ }
29
+ if(assetMatching.length > 1){
30
+ // Warning: File matches multiple assets
31
+ }
32
+ const currentCount = ((): { files: Array<string>, asset: EngineAssetDefinition } =>{
33
+ const currentCount = assetCounts.get(asset.name);
34
+ if(currentCount) return currentCount;
35
+ const newCount = { files: [], asset: asset };
36
+ assetCounts.set(asset.name, newCount);
37
+ return newCount;
38
+ })();
39
+
40
+ currentCount.files.push(filePath);
41
+ fileCounts.set(filePath, { assets: assetMatching });
42
+ }
43
+
44
+ for(const asset of pieceDefinition.assets){
45
+ const currentCountInfo = assetCounts.get(asset.name);
46
+ if(!currentCountInfo){
47
+ // Error: Asset has no files
48
+ assetCounts.set(asset.name, { files: [], asset });
49
+ }
50
+ }
51
+
52
+ return { filesWithAssets: fileCounts, assetsWithFiles: assetCounts };
53
+ }
54
+
55
+ import { isValidAssetFileCount, validateAssetFileCount } from "./validateAssetFileCount";
56
+ export function collectAssetFileErrors(
57
+ { assetsWithFiles, filesWithAssets }: Awaited<ReturnType<typeof getAssetsOfFiles>>
58
+ ){
59
+ const errors: Array<{ type: "asset" | "file", id: string, message: string }> = [];
60
+ for(const [assetName, { asset, files }] of assetsWithFiles){
61
+ try {
62
+ if(files.length === 0 && !isValidAssetFileCount(asset.count, 0)){
63
+ errors.push({
64
+ type: "asset",
65
+ id: assetName,
66
+ message: `Asset is expected to have files`,
67
+ });
68
+ continue;
69
+ }
70
+ validateAssetFileCount(asset.count, files.length);
71
+ }catch(e){
72
+ errors.push({
73
+ type: "asset",
74
+ id: assetName,
75
+ message: (e as Error).message,
76
+ });
77
+ }
78
+ }
79
+ for(const [filePath, { assets }] of filesWithAssets){
80
+ if(assets.length === 0) errors.push({
81
+ type: "file",
82
+ id: filePath,
83
+ message: "File has no matching assets",
84
+ });
85
+ }
86
+ return errors;
87
+ }
88
+
@@ -0,0 +1,42 @@
1
+ import micromatch from "micromatch";
2
+ import { RosterLockV1Config } from "@roster-lock/types";
3
+ type RosterLockEngineConfig = RosterLockV1Config["engine"];
4
+
5
+ import { validatePathVariableValue } from "../../lock/rosters/validate";
6
+ /**
7
+ * Test a single file against piece definition assets
8
+ */
9
+ export function getMatchingAssetsForFile(
10
+ pieceDefinition: RosterLockEngineConfig['pieceDefinitions'][string],
11
+ pathVariables: Record<string, string>,
12
+ relativePath: string,
13
+ ): Array<RosterLockEngineConfig['pieceDefinitions'][string]['assets'][number]> {
14
+
15
+ for(const variableValue of Object.values(pathVariables)){
16
+ validatePathVariableValue(variableValue);
17
+ }
18
+
19
+ return pieceDefinition.assets.filter((asset) =>(
20
+ asset.glob.some((glob)=>{
21
+ // Replace path variables
22
+ glob = replacePathVariables(glob, pathVariables);
23
+ // check if the relativePath is exactly the glob
24
+ // TODO: eventually we want to see if the glob is a file path and if so, check for exact match
25
+ // Relative path isn't expected to have any glob parts, so an exact match is expected to be ok
26
+ // If a filepath can have glob parts, we may be in trouble
27
+ if(relativePath === glob) return true;
28
+ // check if the relativePath matches the glob
29
+ if(micromatch.isMatch(relativePath, glob)) return true;
30
+ return false;
31
+ })
32
+ ));
33
+ }
34
+
35
+ function replacePathVariables(
36
+ glob: string, pathVariables: Record<string, string>
37
+ ){
38
+ for(const [variableName, value] of Object.entries(pathVariables)){
39
+ glob = glob.replaceAll(`<${variableName}>`, value);
40
+ }
41
+ return glob;
42
+ }
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./getAssetsOfFiles";
3
+ export * from "./getMatchingAsset";
4
+ export * from "./validateAssetFileCount";
@@ -0,0 +1,5 @@
1
+ import { RosterLockV1Config } from "@roster-lock/types";
2
+
3
+ export type PieceDefinition = RosterLockV1Config["engine"]["pieceDefinitions"][string];
4
+
5
+ export type EngineAssetDefinition = PieceDefinition["assets"][number];
@@ -0,0 +1,34 @@
1
+ import { EngineAssetDefinition } from "./types";
2
+
3
+ export function validateAssetFileCount(
4
+ validator: EngineAssetDefinition["count"],
5
+ actualCount: number
6
+ ){
7
+ if(!Array.isArray(validator)){
8
+ if(validator === "*") return;
9
+ if(actualCount !== validator){
10
+ throw new Error(`Expected ${validator} files, got ${actualCount}`);
11
+ }
12
+ return;
13
+ }
14
+ const [min, max] = validator;
15
+ if(actualCount < min){
16
+ throw new Error(`Expected at least ${min} files, got ${actualCount}`);
17
+ }
18
+ if(max === "*") return;
19
+ if(actualCount > max){
20
+ throw new Error(`Expected at most ${max} files, got ${actualCount}`);
21
+ }
22
+ }
23
+
24
+ export function isValidAssetFileCount(
25
+ validator: EngineAssetDefinition["count"],
26
+ actualCount: number
27
+ ){
28
+ try {
29
+ validateAssetFileCount(validator, actualCount);
30
+ return true;
31
+ }catch(e){
32
+ return false;
33
+ }
34
+ }
@@ -0,0 +1,6 @@
1
+
2
+ export * from "./files-and-assets";
3
+ export * from "./validate-select";
4
+ export * from "./calculatePieceVersion";
5
+ export * from "./empty-configs";
6
+ export * from "./publish";
@@ -0,0 +1,67 @@
1
+ import { JSON_Unknown } from "@roster-lock/utils";
2
+
3
+ export class SemVer {
4
+ private updateStatus: "none" | "patch" | "minor" | "major" = "none";
5
+ v: {
6
+ major: number,
7
+ minor: number,
8
+ patch: number
9
+ }
10
+ reasons: {
11
+ major: Array<{ reason: string, info: JSON_Unknown }>,
12
+ minor: Array<{ reason: string, info: JSON_Unknown }>,
13
+ patch: Array<{ reason: string, info: JSON_Unknown }>
14
+ } = {
15
+ major: [],
16
+ minor: [],
17
+ patch: [],
18
+ }
19
+ constructor(value: string){
20
+ const parts = value.split(".");
21
+ if(parts.length !== 3) throw new Error("Invalid Semver string");
22
+ this.v = {
23
+ major: SemVer.validateVersion(parts[0], "major"),
24
+ minor: SemVer.validateVersion(parts[1], "minor"),
25
+ patch: SemVer.validateVersion(parts[2], "patch"),
26
+ }
27
+ if(value !== this.toString()){
28
+ throw new Error("Invalid Semver string")
29
+ }
30
+ }
31
+
32
+ addMajor(reason: string, info: JSON_Unknown = {}){
33
+ this.reasons.major.push({ reason, info });
34
+ if(this.updateStatus === "major") return;
35
+ this.updateStatus = "major";
36
+ this.v.major += 1;
37
+ this.v.minor = 0;
38
+ this.v.patch = 0;
39
+ }
40
+ addMinor(reason: string, info: JSON_Unknown = {}){
41
+ this.reasons.minor.push({ reason, info });
42
+ if(this.updateStatus === "minor") return;
43
+ this.updateStatus = "minor";
44
+ this.v.minor += 1;
45
+ this.v.patch = 0;
46
+ }
47
+ addPatch(reason: string, info: JSON_Unknown = {}){
48
+ this.reasons.patch.push({ reason, info });
49
+ if(this.updateStatus === "patch") return;
50
+ this.updateStatus = "patch";
51
+ this.v.patch += 1
52
+ }
53
+
54
+ toString(){
55
+ return [this.v.major, this.v.minor, this.v.patch].join(".")
56
+ }
57
+
58
+ getReasons(){
59
+ return this.reasons;
60
+ }
61
+
62
+ static validateVersion(value: string, partName: string){
63
+ const v = Number.parseInt(value)
64
+ if(Number.isNaN(v)) throw new Error(`Invalid Semver string: ${partName} version not an integer`)
65
+ return v
66
+ }
67
+ }
@@ -0,0 +1,66 @@
1
+ import { RosterLockV1Config } from "@roster-lock/types";
2
+ import { diff } from 'json-diff-ts';
3
+ import { SemVer } from "./SemVer";
4
+
5
+
6
+ export function diffLocks(oldLock: RosterLockV1Config, newLock: RosterLockV1Config){
7
+ const versionTracker = new SemVer(oldLock.version);
8
+
9
+ diffRosters(versionTracker, oldLock, newLock);
10
+
11
+ return versionTracker;
12
+ }
13
+
14
+ function diffRosters(versionTracker: SemVer, oldLock: RosterLockV1Config, newLock: RosterLockV1Config){
15
+ const oldPieceCollections = Object.entries(oldLock.rosters);
16
+ const newPieceCollectionKeys = Object.keys(newLock.rosters);
17
+
18
+ const missingCollections: Array<string> = [];
19
+ const addedCollections = new Set(newPieceCollectionKeys);
20
+
21
+ for(const [key, oldPieces] of oldPieceCollections){
22
+ const newPieces = newLock.rosters[key];
23
+ if(!newPieces){
24
+ versionTracker.addMajor("Missing Piece Collection", { collectionName: key });
25
+ missingCollections.push(key);
26
+ continue;
27
+ }
28
+ addedCollections.delete(key);
29
+ diffPieces(versionTracker, key, oldPieces, newPieces)
30
+ }
31
+ for(const key of addedCollections){
32
+ versionTracker.addMajor("New Piece Collection", { collectionName: key });
33
+ }
34
+
35
+ return versionTracker
36
+ }
37
+
38
+
39
+ type PieceCollection = RosterLockV1Config["rosters"][string]
40
+ type Piece = PieceCollection[number];
41
+ function diffPieces(versionTracker: SemVer, collection: string, oldLock: PieceCollection, newLock: PieceCollection){
42
+ const newPieces = new Map<string, Piece>()
43
+ for(const newPiece of newLock){
44
+ newPieces.set(newPiece.version.logic, newPiece)
45
+ }
46
+ for(const oldPiece of oldLock){
47
+ const newPiece = newPieces.get(oldPiece.version.logic)
48
+ if(!newPiece){
49
+ versionTracker.addMajor(
50
+ "Removed a Piece", { collection, id: oldPiece.id, logic: oldPiece.version.logic }
51
+ )
52
+ continue;
53
+ }
54
+ newPieces.delete(oldPiece.version.logic)
55
+ if(diff(oldPiece, newPiece)){
56
+ versionTracker.addPatch(
57
+ "Updated non gameplay piece info", { collection, id: oldPiece.id, old: oldPiece.downloadSources, new: newPiece.downloadSources }
58
+ )
59
+ }
60
+ }
61
+ for(const [logic, newPiece] of newPieces){
62
+ versionTracker.addMinor(
63
+ "Added a Piece", { collection, id: newPiece.id, logic }
64
+ )
65
+ }
66
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./SemVer";
2
+ export * from "./diffLocks";
@@ -0,0 +1,9 @@
1
+
2
+
3
+ export class RunUntrustedError extends Error {
4
+ constructor(
5
+ public scriptSrc: string, message: string, public error: any
6
+ ){
7
+ super(message)
8
+ }
9
+ }
@@ -0,0 +1,61 @@
1
+
2
+ import { RosterLockV1Config, PieceType, SelectedPiece } from "@roster-lock/types";
3
+
4
+ export function ensurePiecesAreInRoster(
5
+ config: RosterLockV1Config,
6
+ pieceType: PieceType,
7
+ selections: Array<SelectedPiece>
8
+ ){
9
+ const requireConfig = new Set(config.engine.pieceDefinitions[pieceType].requires);
10
+ if(requireConfig.size !== config.engine.pieceDefinitions[pieceType].requires.length){
11
+ throw new Error(`${pieceType} requires has duplicate items`);
12
+ }
13
+ const roster = config.rosters[pieceType];
14
+ for(const piece of selections){
15
+ const rosterPiece = roster.find(p=>p.id === piece.id);
16
+ if(!rosterPiece){
17
+ throw new Error(`Piece ${piece.id} is not in the roster`);
18
+ }
19
+ const pieceRequiredKeys = Object.keys(piece.required);
20
+ if(pieceRequiredKeys.length !== requireConfig.size){
21
+ throw new Error(`Piece ${piece.id} has incorrect number of required keys`);
22
+ }
23
+ for(const requirePieceType of pieceRequiredKeys){
24
+ if(!requireConfig.has(requirePieceType)){
25
+ throw new Error(`Piece ${piece.id} is missing required piece type ${requirePieceType}`);
26
+ }
27
+ ensureCorrectMandatory(rosterPiece, requirePieceType, piece.required[requirePieceType].mandatory);
28
+ ensurePiecesAreInRoster(config, requirePieceType, piece.required[requirePieceType].mandatory);
29
+ ensureSelectionIsAllowed(rosterPiece, requirePieceType, piece.required[requirePieceType].selectable);
30
+ ensurePiecesAreInRoster(config, requirePieceType, piece.required[requirePieceType].selectable);
31
+ }
32
+ }
33
+ }
34
+
35
+ type RosterPiece = RosterLockV1Config["rosters"][string][number];
36
+ function ensureCorrectMandatory(
37
+ rosterPiece: RosterPiece, requiredPieceType: string, mandatoryPieces: Array<SelectedPiece>
38
+ ){
39
+ const rosterMandatory = rosterPiece.requiredPieces[requiredPieceType];
40
+ if(!rosterMandatory) throw new Error(`Roster Piece ${rosterPiece.id} missing required ${requiredPieceType}`);
41
+ if(rosterMandatory.expected.length !== mandatoryPieces.length){
42
+ throw new Error(`Piece ${rosterPiece.id} has incorrect number of required pieces for ${requiredPieceType}`);
43
+ }
44
+ for(let i = 0; i < rosterMandatory.expected.length; i++){
45
+ const mandatoryId = rosterMandatory.expected[i];
46
+ const mandatoryPiece = mandatoryPieces[i];
47
+ if(mandatoryId !== mandatoryPiece.id){
48
+ throw new Error(`Piece ${rosterPiece.id} has incorrect required piece of ${requiredPieceType} at ${i}`);
49
+ }
50
+ }
51
+ }
52
+
53
+ function ensureSelectionIsAllowed(
54
+ rosterPiece: RosterPiece, requiredPieceType: string, selectedPieces: Array<SelectedPiece>
55
+ ){
56
+ const rosterMandatory = rosterPiece.requiredPieces[requiredPieceType];
57
+ if(!rosterMandatory) throw new Error(`Roster Piece ${rosterPiece.id} missing required ${requiredPieceType}`);
58
+ if(!rosterMandatory.selectable && selectedPieces.length > 0){
59
+ throw new Error(`Piece ${rosterPiece.id} does not allow custom selection for ${requiredPieceType}`);
60
+ }
61
+ }
@@ -0,0 +1,54 @@
1
+
2
+ import { RunUntrustedError } from "./constants";
3
+
4
+ export async function handleValidationResult(
5
+ script: { src: string }, result: Promise<unknown>
6
+ ){
7
+ const isValid = await (async ()=>{
8
+ try {
9
+ return await result;
10
+ }catch(e){
11
+ throw new RunUntrustedError(
12
+ script.src, e instanceof Error ? e.message : String(e), e
13
+ );
14
+ }
15
+ })();
16
+ const errorStatus = normalizeError(isValid);
17
+ if(!errorStatus.passed){
18
+ throw new RunUntrustedError(
19
+ script.src, errorStatus.message, isValid
20
+ );
21
+ }
22
+ }
23
+
24
+ const INVALID_VALUE = "Invalid return type for validation";
25
+ const FAILED_WITHOUT_MESSAGE = "Validation Failed";
26
+ function normalizeError(validResult: unknown): (
27
+ | { passed: true }
28
+ | { passed: false, message: string }
29
+ ){
30
+ if(typeof validResult === "boolean"){
31
+ if(validResult) return { passed: true };
32
+ return { passed: false, message: FAILED_WITHOUT_MESSAGE };
33
+ }
34
+ if(Array.isArray(validResult)){
35
+ const [passed, reason] = validResult;
36
+ if(typeof passed !== "boolean"){
37
+ return { passed: false, message: INVALID_VALUE };
38
+ }
39
+ if(passed) return { passed: true };
40
+ return {
41
+ passed: false,
42
+ message: typeof reason === "string" ? reason : FAILED_WITHOUT_MESSAGE,
43
+ };
44
+ }
45
+ if(typeof validResult === "string"){
46
+ return {
47
+ passed: false,
48
+ message: validResult
49
+ };
50
+ }
51
+ if(validResult === null || validResult === void 0) return { passed: true };
52
+ return { passed: false, message: INVALID_VALUE };
53
+ }
54
+