@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.
- package/LICENSE.md +11 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/match-lock-file/config-types.js +3 -0
- package/dist/match-lock-file/config-types.js.map +1 -0
- package/dist/match-lock-file/index.js +19 -0
- package/dist/match-lock-file/index.js.map +1 -0
- package/dist/match-lock-file/match-config/index.js +18 -0
- package/dist/match-lock-file/match-config/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/draft/index.js +44 -0
- package/dist/match-lock-file/match-config/version-1/draft/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/draft/roster-piece-info.js +32 -0
- package/dist/match-lock-file/match-config/version-1/draft/roster-piece-info.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/draft/selection-script-info.js +13 -0
- package/dist/match-lock-file/match-config/version-1/draft/selection-script-info.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/index.js +22 -0
- package/dist/match-lock-file/match-config/version-1/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.js +37 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.js +43 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.js +7 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.js +41 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.js +20 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.js +31 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.js +40 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.js +17 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.js +16 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/index.js +19 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/error.js +25 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/error.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/index.js +33 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.js +31 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.js +37 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.js +22 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.js +24 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.js +39 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.js +46 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.js +23 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.js +99 -0
- package/dist/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/index.js +56 -0
- package/dist/match-lock-file/match-config/version-1/lock/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.js +87 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/index.js +19 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.js +94 -0
- package/dist/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.js +18 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.js +28 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.js +31 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.js +68 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.js +49 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.js +62 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.js +21 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/index.js +19 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.js +10 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/human.js +27 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/human.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/id.js +27 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/id.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/index.js +74 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.js +31 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.js +25 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/utils.js +23 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/utils.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/version.js +19 -0
- package/dist/match-lock-file/match-config/version-1/lock/rosters/validate/version.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.js +42 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.js +46 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.js +12 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.js +49 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.js +32 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.js +12 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/index.js +19 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/index.js +33 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/script.js +23 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/script.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.js +49 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.js +14 -0
- package/dist/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/file-paths.js +5 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/file-paths.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/index.js +23 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/keywords.js +29 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/keywords.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/schema.js +19 -0
- package/dist/match-lock-file/match-config/version-1/piece-info/schema.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/shared/Identity.js +15 -0
- package/dist/match-lock-file/match-config/version-1/shared/Identity.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/shared/SelectedPiece.js +38 -0
- package/dist/match-lock-file/match-config/version-1/shared/SelectedPiece.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/shared/count.js +48 -0
- package/dist/match-lock-file/match-config/version-1/shared/count.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/shared/index.js +25 -0
- package/dist/match-lock-file/match-config/version-1/shared/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/calculatePieceVersion.js +70 -0
- package/dist/match-lock-file/match-config/version-1/usage/calculatePieceVersion.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/empty-configs.js +49 -0
- package/dist/match-lock-file/match-config/version-1/usage/empty-configs.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/constants.js +8 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/constants.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.js +75 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.js +28 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/index.js +20 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/types.js +3 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/types.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.js +33 -0
- package/dist/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/index.js +22 -0
- package/dist/match-lock-file/match-config/version-1/usage/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/SemVer.js +63 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/SemVer.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/diffLocks.js +51 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/diffLocks.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/index.js +19 -0
- package/dist/match-lock-file/match-config/version-1/usage/publish/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/constants.js +14 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/constants.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.js +53 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.js +49 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/index.js +68 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.js +38 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.js +40 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.js +78 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.js +43 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.js.map +1 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.js +26 -0
- package/dist/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.js.map +1 -0
- package/dist/match-lock-file/util-types/json-schema/JSONSchemaCaster.js +45 -0
- package/dist/match-lock-file/util-types/json-schema/JSONSchemaCaster.js.map +1 -0
- package/dist/match-lock-file/util-types/json-schema/defineKeyword.js +30 -0
- package/dist/match-lock-file/util-types/json-schema/defineKeyword.js.map +1 -0
- package/dist/match-lock-file/util-types/json-schema/index.js +21 -0
- package/dist/match-lock-file/util-types/json-schema/index.js.map +1 -0
- package/dist/match-lock-file/util-types/json-schema/safe-keyword.js +3 -0
- package/dist/match-lock-file/util-types/json-schema/safe-keyword.js.map +1 -0
- package/dist/match-lock-file/util-types/json-schema/schema-types.js +3 -0
- package/dist/match-lock-file/util-types/json-schema/schema-types.js.map +1 -0
- package/package.json +49 -0
- package/src/index.ts +3 -0
- package/src/match-lock-file/config-types.ts +10 -0
- package/src/match-lock-file/index.ts +4 -0
- package/src/match-lock-file/match-config/index.ts +2 -0
- package/src/match-lock-file/match-config/version-0/pieces/caster-runtypes/index.ts +99 -0
- package/src/match-lock-file/match-config/version-0/pieces/caster-runtypes/util-casters.ts +155 -0
- package/src/match-lock-file/match-config/version-0/pieces/index.ts +3 -0
- package/src/match-lock-file/match-config/version-0/pieces/types.ts +49 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/definition/assetCount.ts +33 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/definition/assetType.ts +22 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/definition/index.ts +30 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/definition/pathVariables.ts +39 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/index.ts +4 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/sha.ts +23 -0
- package/src/match-lock-file/match-config/version-0/pieces/validate/version.ts +66 -0
- package/src/match-lock-file/match-config/version-0/restriction/casters.ts +52 -0
- package/src/match-lock-file/match-config/version-0/restriction/index.ts +4 -0
- package/src/match-lock-file/match-config/version-0/restriction/types.ts +42 -0
- package/src/match-lock-file/match-config/version-0/restriction/validate/index.ts +15 -0
- package/src/match-lock-file/match-config/version-0/restriction/validate/piece/index.ts +46 -0
- package/src/match-lock-file/match-config/version-0/restriction/validate/sha.ts +19 -0
- package/src/match-lock-file/match-config/version-0/selection/casters.ts +105 -0
- package/src/match-lock-file/match-config/version-0/selection/validate/count.ts +16 -0
- package/src/match-lock-file/match-config/version-0/selection/validate/index.ts +40 -0
- package/src/match-lock-file/match-config/version-0/selection/validate/scriptMeta.ts +26 -0
- package/src/match-lock-file/match-config/version-1/draft/index.ts +52 -0
- package/src/match-lock-file/match-config/version-1/draft/roster-piece-info.ts +33 -0
- package/src/match-lock-file/match-config/version-1/draft/selection-script-info.ts +16 -0
- package/src/match-lock-file/match-config/version-1/index.ts +7 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/index.ts +46 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/asset/keywords.ts +48 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/index.ts +6 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/officialSelections.ts +42 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/index.ts +26 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/requirements/keywords.ts +34 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/schema.ts +47 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.ts +22 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/keywords.ts +14 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/index.ts +3 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/constants.ts +7 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/error.ts +21 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/index.ts +18 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath-component.ts +41 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/filepath.ts +55 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.ts +21 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/pathvariables.ts +28 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/index.ts +46 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/index.ts +37 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.ts +21 -0
- package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/requirements.ts +117 -0
- package/src/match-lock-file/match-config/version-1/lock/index.ts +51 -0
- package/src/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.ts +97 -0
- package/src/match-lock-file/match-config/version-1/lock/piece-meta/index.ts +3 -0
- package/src/match-lock-file/match-config/version-1/lock/piece-meta/validate/index.ts +114 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/downloadableSources.ts +25 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/human.ts +33 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/id.ts +33 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/index.ts +103 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/pathVariables.ts +59 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/requiresPieces.ts +71 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/caster-json-schema/version.ts +22 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/index.ts +3 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/downloadable-source.ts +9 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/human.ts +22 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/id.ts +20 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/index.ts +83 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/path-variables.ts +40 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/required-pieces.ts +30 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/utils.ts +17 -0
- package/src/match-lock-file/match-config/version-1/lock/rosters/validate/version.ts +22 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/index.ts +53 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/script.ts +54 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/game-controlled.ts +11 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/normal.ts +58 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/preselected.ts +37 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/caster-json-schema/selection-types/unselectable.ts +11 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/index.ts +3 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/validate/index.ts +37 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/validate/script.ts +28 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/validate/selections/normal.ts +69 -0
- package/src/match-lock-file/match-config/version-1/lock/selection/validate/selections/preselected.ts +18 -0
- package/src/match-lock-file/match-config/version-1/piece-info/file-paths.ts +2 -0
- package/src/match-lock-file/match-config/version-1/piece-info/index.ts +14 -0
- package/src/match-lock-file/match-config/version-1/piece-info/keywords.ts +39 -0
- package/src/match-lock-file/match-config/version-1/piece-info/schema.ts +29 -0
- package/src/match-lock-file/match-config/version-1/shared/Identity.ts +14 -0
- package/src/match-lock-file/match-config/version-1/shared/SelectedPiece.ts +49 -0
- package/src/match-lock-file/match-config/version-1/shared/count.ts +47 -0
- package/src/match-lock-file/match-config/version-1/shared/index.ts +9 -0
- package/src/match-lock-file/match-config/version-1/usage/calculatePieceVersion.ts +85 -0
- package/src/match-lock-file/match-config/version-1/usage/empty-configs.ts +61 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/constants.ts +6 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/getAssetsOfFiles.ts +88 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/getMatchingAsset.ts +42 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/index.ts +4 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/types.ts +5 -0
- package/src/match-lock-file/match-config/version-1/usage/files-and-assets/validateAssetFileCount.ts +34 -0
- package/src/match-lock-file/match-config/version-1/usage/index.ts +6 -0
- package/src/match-lock-file/match-config/version-1/usage/publish/SemVer.ts +67 -0
- package/src/match-lock-file/match-config/version-1/usage/publish/diffLocks.ts +66 -0
- package/src/match-lock-file/match-config/version-1/usage/publish/index.ts +2 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/constants.ts +9 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/ensure-pieces-are-in-roster.ts +61 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/handle-validation.ts +54 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/index.ts +98 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/game-controlled.ts +49 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/cast-result.ts +39 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/include-mandatory-require.ts +44 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/index.ts +101 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/normal/validate-user-selection.ts +51 -0
- package/src/match-lock-file/match-config/version-1/usage/validate-select/selection-types/preselected.ts +36 -0
- package/src/match-lock-file/util-types/json-schema/JSONSchemaCaster.ts +52 -0
- package/src/match-lock-file/util-types/json-schema/checkVersion.ts +9 -0
- package/src/match-lock-file/util-types/json-schema/defineKeyword.ts +50 -0
- package/src/match-lock-file/util-types/json-schema/index.ts +4 -0
- package/src/match-lock-file/util-types/json-schema/safe-keyword.ts +27 -0
- package/src/match-lock-file/util-types/json-schema/schema-types.ts +5 -0
- package/tests/engine/assets.spec.ts +147 -0
- package/tests/engine/official-selections.spec.ts +67 -0
- package/tests/engine/requirements.spec.ts +43 -0
- package/tests/piece-info/cast.spec.ts +20 -0
- package/tests/piece-info/rosterlock.piece-info.json +15 -0
- package/tests/piece-meta/cast.spec.ts +60 -0
- package/tests/rosters/path-variables.spec.ts +52 -0
- package/tests/selection/cast-result.spec.ts +72 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { JSONSchemaType } from "ajv";
|
|
2
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
3
|
+
type RosterLockEngineConfig = RosterLockV1Config["engine"];
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import { assetsSchema, assetKeywords } from "./asset";
|
|
7
|
+
import { requirementsSchema, requirementKeywords } from "./requirements";
|
|
8
|
+
import { pathVariablesSchema, pathVariableKeywords } from "./variables";
|
|
9
|
+
import { officialSelectionsSchema, officialSelectionsKeywords } from "./officialSelections";
|
|
10
|
+
|
|
11
|
+
const pieceDefinitionSchema: JSONSchemaType<
|
|
12
|
+
RosterLockEngineConfig["pieceDefinitions"][string]
|
|
13
|
+
> = {
|
|
14
|
+
type: "object",
|
|
15
|
+
required: ["selectionStrategy", "requires", "pathVariables", "assets"],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
properties: {
|
|
18
|
+
selectionStrategy: { type: "string", enum: ["mandatory", "personal", "shared", "on demand"] },
|
|
19
|
+
pathVariables: pathVariablesSchema,
|
|
20
|
+
requires: requirementsSchema,
|
|
21
|
+
assets: assetsSchema,
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const engineSchema: JSONSchemaType<RosterLockEngineConfig> = {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["name", "version", "pieceDefinitions"],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
properties: {
|
|
30
|
+
name: { type: "string" },
|
|
31
|
+
version: { type: "string" },
|
|
32
|
+
pieceDefinitions: {
|
|
33
|
+
type: "object",
|
|
34
|
+
required: [],
|
|
35
|
+
additionalProperties: pieceDefinitionSchema
|
|
36
|
+
},
|
|
37
|
+
officialSelections: { ...officialSelectionsSchema, nullable: true },
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const engineKeywords = [
|
|
42
|
+
...pathVariableKeywords,
|
|
43
|
+
...requirementKeywords,
|
|
44
|
+
...assetKeywords,
|
|
45
|
+
...officialSelectionsKeywords,
|
|
46
|
+
]
|
|
47
|
+
|
package/src/match-lock-file/match-config/version-1/lock/engine/caster-json-schema/variables/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
import { JSONSchemaType } from "ajv";
|
|
3
|
+
import { pathVariableListSchemaValidator, pathVariableNameSchemaValidator } from "./keywords";
|
|
4
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
5
|
+
type RosterLockEngineConfig = RosterLockV1Config["engine"];
|
|
6
|
+
|
|
7
|
+
export const pathVariableKeywords = [
|
|
8
|
+
pathVariableListSchemaValidator,
|
|
9
|
+
pathVariableNameSchemaValidator,
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export const pathVariablesSchema: JSONSchemaType<
|
|
14
|
+
RosterLockEngineConfig["pieceDefinitions"][string]["pathVariables"]
|
|
15
|
+
> = {
|
|
16
|
+
[pathVariableListSchemaValidator.keyword]: true,
|
|
17
|
+
type: "array",
|
|
18
|
+
items: {
|
|
19
|
+
[pathVariableNameSchemaValidator.keyword]: true,
|
|
20
|
+
type: "string",
|
|
21
|
+
},
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineKeyword } from "../../../../../../util-types/json-schema";
|
|
2
|
+
|
|
3
|
+
import { validatePathVariables, validatePathVariableName } from "../../validate/piece/path-variables";
|
|
4
|
+
export const pathVariableListSchemaValidator = defineKeyword({
|
|
5
|
+
keyword: "enginePathVariableList",
|
|
6
|
+
type: "array",
|
|
7
|
+
validate: validatePathVariables
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const pathVariableNameSchemaValidator = defineKeyword({
|
|
11
|
+
keyword: "enginePathVariableName",
|
|
12
|
+
type: "string",
|
|
13
|
+
validate: validatePathVariableName
|
|
14
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export class ValidationErrorPath extends Error {
|
|
4
|
+
path = "/";
|
|
5
|
+
constructor(message: string){
|
|
6
|
+
super(message);
|
|
7
|
+
}
|
|
8
|
+
addPathPrefix(part: string){
|
|
9
|
+
this.path = `/${part}${this.path}`;
|
|
10
|
+
}
|
|
11
|
+
addPathSuffix(part: string){
|
|
12
|
+
this.path = `${this.path}/${part}`;
|
|
13
|
+
}
|
|
14
|
+
static convertError(e: unknown){
|
|
15
|
+
if(!(e instanceof Error)) throw e;
|
|
16
|
+
if(!(e instanceof ValidationErrorPath)){
|
|
17
|
+
e = new ValidationErrorPath(e.message);
|
|
18
|
+
}
|
|
19
|
+
return e as ValidationErrorPath;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import { validatePieceDefinition } from "./piece";
|
|
3
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
4
|
+
|
|
5
|
+
export * from "./piece";
|
|
6
|
+
import { ValidationErrorPath } from "./error";
|
|
7
|
+
|
|
8
|
+
export function validateEngineConfig(engine: RosterLockV1Config["engine"]){
|
|
9
|
+
for(const [pieceType, definition] of Object.entries(engine.pieceDefinitions)){
|
|
10
|
+
try {
|
|
11
|
+
validatePieceDefinition(pieceType, definition, engine);
|
|
12
|
+
}catch(e){
|
|
13
|
+
const eTyped = ValidationErrorPath.convertError(e);
|
|
14
|
+
eTyped.addPathPrefix(`pieceDefinitions/${pieceType}`);
|
|
15
|
+
throw e;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
const WINDOWS_RESERVED_NAMES = [
|
|
3
|
+
'CON', 'PRN', 'AUX', 'NUL',
|
|
4
|
+
'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
|
|
5
|
+
'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export function isValidPathComponent(component: string) {
|
|
9
|
+
// Empty components are invalid
|
|
10
|
+
if(component.length === 0){
|
|
11
|
+
throw new Error("Filepath component is empty");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Check component length (most filesystems have per-component limits)
|
|
15
|
+
if(component.length > 255){
|
|
16
|
+
throw new Error("Filepath component is too long");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Reserved names on Windows (even on other platforms, better to be safe)
|
|
20
|
+
const upperComponent = component.toUpperCase();
|
|
21
|
+
const baseName = upperComponent.split('.')[0]; // Remove extension for check
|
|
22
|
+
if(WINDOWS_RESERVED_NAMES.includes(baseName)){
|
|
23
|
+
throw new Error("Filepath component is a reserved name");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Must not start or end with spaces (problematic on Windows)
|
|
27
|
+
// Note: Leading dots are actually valid (hidden files on Unix)
|
|
28
|
+
if(component.startsWith(' ') || component.endsWith(' ')){
|
|
29
|
+
throw new Error("Filepath component has leading/trailing spaces");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Must not end with dots (problematic on Windows)
|
|
33
|
+
if(component.endsWith('.')){
|
|
34
|
+
throw new Error("Filepath component ends with a dot");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Must not be just dots
|
|
38
|
+
if(/^\.+$/.test(component)){
|
|
39
|
+
throw new Error("Filepath component is just dots");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
import { isValidPathComponent } from "./filepath-component";
|
|
3
|
+
export function isValidFilePath(path: string) {
|
|
4
|
+
// Comprehensive validation for file paths
|
|
5
|
+
if(path.length === 0){
|
|
6
|
+
throw new Error("Filepath is empty");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Check path length limits (most filesystems have limits)
|
|
10
|
+
if(path.length > 4096){
|
|
11
|
+
throw new Error("Filepath is too long");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Only forward slashes allowed - reject backslashes for cross-platform consistency
|
|
15
|
+
if(path.includes('\\')){
|
|
16
|
+
throw new Error("Filepath contains backslash - use forward slashes only");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check for invalid characters across different platforms
|
|
20
|
+
// Windows: < > : " | ? * and control characters (0x00-0x1f)
|
|
21
|
+
// Unix/Linux: null character (0x00) and forward slash in filenames
|
|
22
|
+
// We'll be restrictive and block characters that are problematic on any major platform
|
|
23
|
+
const invalidChars = /[<>:"|?*\x00-\x1f\x7f]/;
|
|
24
|
+
if(invalidChars.test(path)){
|
|
25
|
+
throw new Error("Filepath contains invalid characters");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check for relative path traversal attempts
|
|
29
|
+
if(
|
|
30
|
+
path.includes('../') ||
|
|
31
|
+
path.includes('/..') ||
|
|
32
|
+
path === '..' ||
|
|
33
|
+
path.startsWith('../') ||
|
|
34
|
+
path.endsWith('/..')
|
|
35
|
+
){
|
|
36
|
+
throw new Error("Filepath contains invalid traversal");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Must not end with a slash (indicating a directory)
|
|
40
|
+
if(path.endsWith('/')){
|
|
41
|
+
throw new Error("Filepath ends with a slash");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Split into path components and validate each
|
|
45
|
+
const components = path.split('/');
|
|
46
|
+
for(const component of components){
|
|
47
|
+
isValidPathComponent(component);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Must have at least one component (the filename)
|
|
51
|
+
if(components.length === 0){
|
|
52
|
+
throw new Error("Filepath has no components");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/assets/glob/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import isGlob from "is-glob";
|
|
2
|
+
|
|
3
|
+
export { validatePathVariablesInGlob } from "./pathvariables";
|
|
4
|
+
import { replacePathVariablesWithGlob } from "./pathvariables";
|
|
5
|
+
import { isValidFilePath } from "./filepath";
|
|
6
|
+
export function validateGlobItem(pattern: string) {
|
|
7
|
+
// First, check if the glob uses any undefined path variables
|
|
8
|
+
pattern = replacePathVariablesWithGlob(pattern);
|
|
9
|
+
|
|
10
|
+
// Check for absolute paths (we want relative paths only)
|
|
11
|
+
if(pattern.startsWith('/') || /^[a-zA-Z]:/.test(pattern)){
|
|
12
|
+
throw new Error("File pattern is absolute");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// If it's a valid glob pattern, accept it
|
|
16
|
+
if(isGlob(pattern)) return;
|
|
17
|
+
|
|
18
|
+
// If it's not a glob, check if it's a valid file path
|
|
19
|
+
isValidFilePath(pattern);
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
export const PATH_VARIABLE_VALUE_VALIDATION = {
|
|
3
|
+
minLength: 1,
|
|
4
|
+
maxLength: 64,
|
|
5
|
+
charset: 'a-zA-Z0-9_\\- ',
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function validatePathVariablesInGlob(
|
|
9
|
+
glob: string, pathVariables: Array<string>
|
|
10
|
+
){
|
|
11
|
+
const pathVariableRegex = /<([a-zA-Z0-9_\\-]+)>/g;
|
|
12
|
+
let match: RegExpExecArray | null;
|
|
13
|
+
while((match = pathVariableRegex.exec(glob)) !== null){
|
|
14
|
+
const variable = match[1];
|
|
15
|
+
if(!pathVariables.includes(variable)){
|
|
16
|
+
throw new Error(`Glob ${glob} uses undefined path variable ${variable}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function replacePathVariablesWithGlob(
|
|
22
|
+
glob: string
|
|
23
|
+
){
|
|
24
|
+
return glob.replaceAll(
|
|
25
|
+
/<([a-zA-Z0-9_\\-]+)>/g,
|
|
26
|
+
`[[${PATH_VARIABLE_VALUE_VALIDATION.charset}]+]{${PATH_VARIABLE_VALUE_VALIDATION.minLength},${PATH_VARIABLE_VALUE_VALIDATION.maxLength}}`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
2
|
+
type RosterLockEngineConfig = RosterLockV1Config["engine"];
|
|
3
|
+
type EngineAssetDefinition = RosterLockEngineConfig["pieceDefinitions"][string]["assets"][number];
|
|
4
|
+
|
|
5
|
+
import { validateCount } from "../../../../../shared/count";
|
|
6
|
+
|
|
7
|
+
export function validateAsset(
|
|
8
|
+
pieceAssetDefinition: RosterLockEngineConfig["pieceDefinitions"][string]["assets"][0],
|
|
9
|
+
definition: RosterLockEngineConfig["pieceDefinitions"][string]
|
|
10
|
+
){
|
|
11
|
+
validateAssetName(pieceAssetDefinition.name, definition.assets);
|
|
12
|
+
validateCount(pieceAssetDefinition.count);
|
|
13
|
+
validateGlobList(pieceAssetDefinition.glob);
|
|
14
|
+
for(const g of pieceAssetDefinition.glob){
|
|
15
|
+
validatePathVariablesInGlob(g, definition.pathVariables);
|
|
16
|
+
validateGlobItem(g);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function validateAssetName(
|
|
21
|
+
name: EngineAssetDefinition["name"], assets: RosterLockEngineConfig["pieceDefinitions"][string]["assets"]
|
|
22
|
+
){
|
|
23
|
+
if(name === ""){
|
|
24
|
+
throw new Error("Name is empty");
|
|
25
|
+
}
|
|
26
|
+
if(name !== name.trim()){
|
|
27
|
+
throw new Error("Name contains a trailing or leading space");
|
|
28
|
+
}
|
|
29
|
+
if(assets.filter((a) => a.name === name).length > 1){
|
|
30
|
+
throw new Error("Duplicate name");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
import { validatePathVariablesInGlob, validateGlobItem } from "./glob";
|
|
35
|
+
export function validateGlobList(
|
|
36
|
+
glob: EngineAssetDefinition["glob"],
|
|
37
|
+
){
|
|
38
|
+
if(glob.length === 0){
|
|
39
|
+
throw new Error("Expecting at least 1 glob");
|
|
40
|
+
}
|
|
41
|
+
if(new Set(glob).size !== glob.length){
|
|
42
|
+
throw new Error("Has duplicate globs");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { validatePathVariablesInGlob, validateGlobItem };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
2
|
+
type RosterLockEngineConfig = RosterLockV1Config["engine"];
|
|
3
|
+
|
|
4
|
+
export * from "./requirements";
|
|
5
|
+
export * from "./path-variables";
|
|
6
|
+
export * from "./assets";
|
|
7
|
+
import { validatePathVariableName, validatePathVariables } from "./path-variables";
|
|
8
|
+
import { validateAsset } from "./assets";
|
|
9
|
+
import {
|
|
10
|
+
validatePieceInCycles, validatePieceRequirementList, validatePieceRequirementIsResolved
|
|
11
|
+
} from "./requirements";
|
|
12
|
+
import { ValidationErrorPath } from "../error";
|
|
13
|
+
|
|
14
|
+
export function validatePieceDefinition(
|
|
15
|
+
pieceType: string, definition: RosterLockEngineConfig["pieceDefinitions"][string], engine: RosterLockEngineConfig
|
|
16
|
+
){
|
|
17
|
+
validatePieceRequirementList(definition.requires);
|
|
18
|
+
for(const requiredPieceType of definition.requires){
|
|
19
|
+
validatePieceRequirementIsResolved(requiredPieceType, engine);
|
|
20
|
+
}
|
|
21
|
+
validatePathVariables(definition.pathVariables);
|
|
22
|
+
for(const variable of definition.pathVariables){
|
|
23
|
+
validatePathVariableName(variable);
|
|
24
|
+
}
|
|
25
|
+
for(const asset of definition.assets){
|
|
26
|
+
try {
|
|
27
|
+
validateAsset(asset, definition);
|
|
28
|
+
}catch(e){
|
|
29
|
+
const eTyped = ValidationErrorPath.convertError(e);
|
|
30
|
+
eTyped.addPathPrefix(`assets/${asset.name}`);
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
validatePieceInCycles(pieceType, engine);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
package/src/match-lock-file/match-config/version-1/lock/engine/validate/piece/path-variables.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
export function validatePathVariables(variables: Array<string>){
|
|
3
|
+
if(new Set(variables).size !== variables.length){
|
|
4
|
+
throw new Error(`Duplicate path variables`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Note: [^CHARS] specifies we're looking for characters that are NOT in the set
|
|
9
|
+
const INVALID_PATH_VARIABLE_CHARS = /[^a-zA-Z0-9_]/;
|
|
10
|
+
export function validatePathVariableName(variable: string){
|
|
11
|
+
if(variable.length === 0){
|
|
12
|
+
throw new Error(`Path variable is empty`);
|
|
13
|
+
}
|
|
14
|
+
if(variable.length > 64){
|
|
15
|
+
throw new Error(`Path variable ${variable} is too long`);
|
|
16
|
+
}
|
|
17
|
+
const match = variable.match(INVALID_PATH_VARIABLE_CHARS)
|
|
18
|
+
if(match){
|
|
19
|
+
throw new Error(`Path variable ${variable} contains invalid character: "${match[0]}"`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { findAllCycles, getCyclesUsingKey } from "@roster-lock/utils";
|
|
2
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
3
|
+
type RosterLockEngineConfig = RosterLockV1Config["engine"];
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export class CycleError extends Error {
|
|
7
|
+
constructor(public cycles: Array<Array<string>>){
|
|
8
|
+
super(`Piece requirements form a cycle`);
|
|
9
|
+
}
|
|
10
|
+
getCyclesOfPiece(pieceType: string){
|
|
11
|
+
return getCyclesUsingKey(pieceType, this.cycles);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function validatePieceRequirementCycles(engine: RosterLockEngineConfig){
|
|
16
|
+
const pieceTypes = Object.keys(engine.pieceDefinitions);
|
|
17
|
+
const cycles = findAllCycles(pieceTypes, (pieceType) => engine.pieceDefinitions[pieceType].requires);
|
|
18
|
+
if(cycles.length > 0) throw new CycleError(cycles);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function validatePieceInCycles(pieceType: string, engine: RosterLockEngineConfig){
|
|
22
|
+
const pieceTypes = Object.keys(engine.pieceDefinitions);
|
|
23
|
+
const cycles = findAllCycles(pieceTypes, (pieceType) => engine.pieceDefinitions[pieceType].requires);
|
|
24
|
+
if(cycles.length === 0) return;
|
|
25
|
+
const pieceCycles = getCyclesUsingKey(pieceType, cycles);
|
|
26
|
+
if(pieceCycles.length === 0) return;
|
|
27
|
+
throw new CycleError(pieceCycles);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function validatePieceRequirementList(
|
|
31
|
+
requires: Array<string>
|
|
32
|
+
){
|
|
33
|
+
if(requires.length === 0) return;
|
|
34
|
+
if(new Set(requires).size !== requires.length)
|
|
35
|
+
throw new Error(`Duplicate requires`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function validatePieceRequirementIsResolved(
|
|
39
|
+
requiredPieceType: RosterLockEngineConfig["pieceDefinitions"][string]["requires"][0],
|
|
40
|
+
engine: RosterLockEngineConfig
|
|
41
|
+
){
|
|
42
|
+
const requiredDefinition = engine.pieceDefinitions[requiredPieceType];
|
|
43
|
+
if(!requiredDefinition){
|
|
44
|
+
throw new Error(`Non-existant piece ${requiredPieceType} required`);
|
|
45
|
+
}
|
|
46
|
+
if(requiredDefinition.selectionStrategy !== "on demand"){
|
|
47
|
+
throw new Error(`Non on-demand piece ${requiredPieceType} required`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// This version tries to use the minimum amount of loops possible
|
|
54
|
+
// Ensure that pieces not on demand can't be required by another non on demand piece
|
|
55
|
+
// Ensure all on demand pieces are required by another piece
|
|
56
|
+
export function eachPieceRequirementIsResolved_COMPLEX(engine: RosterLockEngineConfig){
|
|
57
|
+
const notOnDemandPieceTypes = new Set<string>();
|
|
58
|
+
const unusedOnDemandPieceTypes = new Set<string>();
|
|
59
|
+
const usedOnDemandPieceTypes = new Set<string>();
|
|
60
|
+
const expectedRequires = new Set<string>();
|
|
61
|
+
for(const [pieceType, definition] of Object.entries(engine.pieceDefinitions)){
|
|
62
|
+
// If the piece is on demand, we don't need to resolve it
|
|
63
|
+
if(definition.selectionStrategy === "on demand"){
|
|
64
|
+
if(usedOnDemandPieceTypes.has(pieceType)) continue;
|
|
65
|
+
expectedRequires.delete(pieceType);
|
|
66
|
+
unusedOnDemandPieceTypes.add(pieceType);
|
|
67
|
+
|
|
68
|
+
if(definition.requires.length === 0) continue;
|
|
69
|
+
if(new Set(definition.requires).size !== definition.requires.length)
|
|
70
|
+
throw new Error(`Piece ${pieceType} has duplicate requires`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// If the piece is not on demand, It can't be required
|
|
75
|
+
if(expectedRequires.has(pieceType)){
|
|
76
|
+
throw new Error(`Piece ${pieceType} is required by another piece but is not an on demand piece`);
|
|
77
|
+
}
|
|
78
|
+
notOnDemandPieceTypes.add(pieceType);
|
|
79
|
+
|
|
80
|
+
// If we have no requirements, we're done
|
|
81
|
+
if(definition.requires.length === 0) continue;
|
|
82
|
+
if(new Set(definition.requires).size !== definition.requires.length)
|
|
83
|
+
throw new Error(`Piece ${pieceType} has duplicate requires`);
|
|
84
|
+
|
|
85
|
+
checkRequires(pieceType, definition);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if(expectedRequires.size > 0){
|
|
89
|
+
throw new Error(`The following pieces are required but not resolved: ${Array.from(expectedRequires).join(", ")}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function checkRequires(pieceType: string, definition: RosterLockEngineConfig["pieceDefinitions"][string]){
|
|
93
|
+
|
|
94
|
+
// Check each required piece type
|
|
95
|
+
for(const requiredPieceType of definition.requires){
|
|
96
|
+
// If the required piece type was already resolved, we're ok
|
|
97
|
+
if(notOnDemandPieceTypes.has(requiredPieceType)){
|
|
98
|
+
throw new Error(`Piece ${requiredPieceType} is required by another piece but is not an on demand piece`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// If the required piece type was already used, we're ok
|
|
102
|
+
if(usedOnDemandPieceTypes.has(requiredPieceType)) continue;
|
|
103
|
+
|
|
104
|
+
// If the required piece type is on demand but wasn't used, we need to resolve it
|
|
105
|
+
if(unusedOnDemandPieceTypes.has(requiredPieceType)){
|
|
106
|
+
unusedOnDemandPieceTypes.delete(requiredPieceType);
|
|
107
|
+
usedOnDemandPieceTypes.add(requiredPieceType);
|
|
108
|
+
checkRequires(requiredPieceType, engine.pieceDefinitions[requiredPieceType]);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Otherwise the on demand piece is not defined yet, we expect to find it later
|
|
113
|
+
expectedRequires.add(requiredPieceType);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
import { JSONSchemaType } from "ajv";
|
|
3
|
+
import { JSONSchemaCaster } from "../../../util-types/json-schema";
|
|
4
|
+
import { engineKeywords, engineSchema } from "./engine";
|
|
5
|
+
export * from "./engine";
|
|
6
|
+
import { rosterKeywords, rostersSchema } from "./rosters";
|
|
7
|
+
export * from "./rosters";
|
|
8
|
+
import { selectionKeywords, selectionConfigSchema } from "./selection";
|
|
9
|
+
export * from "./selection";
|
|
10
|
+
import { pieceMetaKeywords, pieceMetaSchema } from "./piece-meta";
|
|
11
|
+
export * from "./piece-meta";
|
|
12
|
+
import { sharedKeywords } from "../shared";
|
|
13
|
+
|
|
14
|
+
import { RosterLockV1Config } from "@roster-lock/types";
|
|
15
|
+
|
|
16
|
+
import { buildIdentity } from "../shared";
|
|
17
|
+
|
|
18
|
+
export const RosterLockV1Schema: JSONSchemaType<RosterLockV1Config> = {
|
|
19
|
+
type: "object",
|
|
20
|
+
required: [
|
|
21
|
+
"configIdentity",
|
|
22
|
+
"author", "title", "version",
|
|
23
|
+
"engine", "rosters", "selection", "pieceMeta"
|
|
24
|
+
],
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
properties: {
|
|
27
|
+
configIdentity: buildIdentity("lock", 1),
|
|
28
|
+
|
|
29
|
+
author: { type: "string" },
|
|
30
|
+
title: { type: "string" },
|
|
31
|
+
version: { type: "string" },
|
|
32
|
+
|
|
33
|
+
engine: engineSchema,
|
|
34
|
+
rosters: rostersSchema,
|
|
35
|
+
selection: selectionConfigSchema,
|
|
36
|
+
pieceMeta: pieceMetaSchema,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const RosterLockV1SchemaKeywords = [
|
|
41
|
+
...sharedKeywords,
|
|
42
|
+
...engineKeywords,
|
|
43
|
+
...rosterKeywords,
|
|
44
|
+
...selectionKeywords,
|
|
45
|
+
...pieceMetaKeywords,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
export const ROSTERLOCK_V1_CASTER_JSONSCHEMA = new JSONSchemaCaster<
|
|
50
|
+
RosterLockV1Config
|
|
51
|
+
>(RosterLockV1Schema,RosterLockV1SchemaKeywords);
|
package/src/match-lock-file/match-config/version-1/lock/piece-meta/caster-json-schema/index.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
|
|
2
|
+
import { JSONSchemaType } from "ajv";
|
|
3
|
+
import { defineKeyword } from "../../../../../util-types/json-schema";
|
|
4
|
+
import { RosterLockV1Config, SelectionPieceMeta, JSONShallowObject } from "@roster-lock/types";
|
|
5
|
+
|
|
6
|
+
import { validateMetaDefaultValue, validateMetaForPiece } from "../validate";
|
|
7
|
+
|
|
8
|
+
export const metaDefaultValueSchemaValidator = defineKeyword({
|
|
9
|
+
keyword: "metaDefaultValue",
|
|
10
|
+
type: "object",
|
|
11
|
+
validate: (defaultMeta: JSONShallowObject, { pieceMeta }: RosterLockV1Config, path)=>{
|
|
12
|
+
const pathParts = path.split("/");
|
|
13
|
+
// /pieceMeta/pieceType/defaultMeta
|
|
14
|
+
const pieceType = pathParts[2];
|
|
15
|
+
const sharedPieceMeta = pieceMeta[pieceType];
|
|
16
|
+
if(!sharedPieceMeta){
|
|
17
|
+
throw new Error(`Piece type ${pieceType} does not have shared piece meta`);
|
|
18
|
+
}
|
|
19
|
+
validateMetaDefaultValue(sharedPieceMeta.schema, defaultMeta);
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export const metaPieceValueSchemaValidator = defineKeyword({
|
|
25
|
+
keyword: "metaPieceValue",
|
|
26
|
+
type: "object",
|
|
27
|
+
validate: (pieceValue: JSONShallowObject, { pieceMeta, rosters }: RosterLockV1Config, path)=>{
|
|
28
|
+
const pathParts = path.split("/");
|
|
29
|
+
// /pieceMeta/pieceType/values/pieceId
|
|
30
|
+
const pieceType = pathParts[2];
|
|
31
|
+
const pieceId = pathParts[4]?.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
32
|
+
const sharedPieceMeta = pieceMeta[pieceType];
|
|
33
|
+
if(!sharedPieceMeta){
|
|
34
|
+
throw new Error(`Piece type ${pieceType} does not have shared piece meta`);
|
|
35
|
+
}
|
|
36
|
+
const roster = rosters[pieceType];
|
|
37
|
+
if(!roster){
|
|
38
|
+
throw new Error(`Piece type ${pieceType} does not have a roster`);
|
|
39
|
+
}
|
|
40
|
+
validateMetaForPiece(sharedPieceMeta.schema, pieceId, pieceValue, roster);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const shallowObjectSchema = {
|
|
45
|
+
type: "object",
|
|
46
|
+
required: [],
|
|
47
|
+
additionalProperties: {
|
|
48
|
+
anyOf: [
|
|
49
|
+
{ type: "string" },
|
|
50
|
+
{ type: "number" },
|
|
51
|
+
{ type: "boolean" },
|
|
52
|
+
{ type: "array", items: { type: "string" } },
|
|
53
|
+
{ type: "array", items: { type: "number" } },
|
|
54
|
+
{ type: "array", items: { type: "boolean" } },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export const selectionPieceMetaSchema: JSONSchemaType<SelectionPieceMeta<JSONShallowObject>> = {
|
|
61
|
+
type: "object",
|
|
62
|
+
required: ["schema","defaultMeta", "values"],
|
|
63
|
+
additionalProperties: false,
|
|
64
|
+
properties: {
|
|
65
|
+
schema: {
|
|
66
|
+
type: "object",
|
|
67
|
+
required: [],
|
|
68
|
+
additionalProperties: {
|
|
69
|
+
type: "string",
|
|
70
|
+
enum: ["boolean", "number", "string", "boolean[]", "number[]", "string[]"],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
defaultMeta: {
|
|
74
|
+
...shallowObjectSchema,
|
|
75
|
+
[metaDefaultValueSchemaValidator.keyword]: true,
|
|
76
|
+
},
|
|
77
|
+
values: {
|
|
78
|
+
type: "object",
|
|
79
|
+
required: [],
|
|
80
|
+
additionalProperties: {
|
|
81
|
+
...shallowObjectSchema,
|
|
82
|
+
[metaPieceValueSchemaValidator.keyword]: true,
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const pieceMetaSchema: JSONSchemaType<RosterLockV1Config["pieceMeta"]> = {
|
|
89
|
+
type: "object",
|
|
90
|
+
required: [],
|
|
91
|
+
additionalProperties: selectionPieceMetaSchema,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const pieceMetaKeywords = [
|
|
95
|
+
metaDefaultValueSchemaValidator,
|
|
96
|
+
metaPieceValueSchemaValidator,
|
|
97
|
+
];
|