From d8aef49a92f9d30c78c554207ee656de774549c6 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 12:20:41 -0700 Subject: [PATCH 01/18] Replace json schema with openapi --- schema/indexSchema.json | 34 -- schema/manifestSchema.json | 677 ------------------------------------- schema/openapi.yaml | 471 ++++++++++++++++++++++++++ 3 files changed, 471 insertions(+), 711 deletions(-) delete mode 100644 schema/indexSchema.json delete mode 100644 schema/manifestSchema.json create mode 100644 schema/openapi.yaml diff --git a/schema/indexSchema.json b/schema/indexSchema.json deleted file mode 100644 index 6075a334..00000000 --- a/schema/indexSchema.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/ReviversMC/the-mod-index/blob/v3/schema/indexSchema.json", - "title": "Index Schema", - "description": "The file to search when searching for mods.", - "type": "object", - "properties": { - "indexVersion": { - "type": "string", - "description": "The semver version of the targeted index.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" - }, - "identifiers": { - "type": "array", - "description": "The identifiers of the manifests available", - "items": { - "type": "string", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+:[a-z0-9]{15}$" - } - }, - "eolEpochTime": { - "type": [ - "integer", - null - ], - "description": "The epoch time when index version will no longer receive mod updates. May be larger than a 32 bit integer." - } - }, - "required": [ - "identifier", - "sha512Hash", - "eolEpochTime" - ] -} diff --git a/schema/manifestSchema.json b/schema/manifestSchema.json deleted file mode 100644 index eb5541bc..00000000 --- a/schema/manifestSchema.json +++ /dev/null @@ -1,677 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/ReviversMC/the-mod-index/blob/v3/schema/manifestSchema.json", - "title": "Manifest Schema", - "description": "The file for each of a mod per its loader", - "type": "object", - "properties": { - "indexVersion": { - "type": "string", - "description": "The semver version of the targeted index.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" - }, - "genericIdentifier": { - "type": "string", - "description": "The fancy name of the mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - }, - "fancyName": { - "type": "string", - "description": "The fancy name of the mod.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "author": { - "type": "string", - "description": "The author of the mod.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "license": { - "type": [ - "string", - null - ], - "description": "The license of the mod, or url if not a standard license.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "curseForgeId": { - "type": [ - "integer", - null - ], - "description": "The curseforge id of the mod." - }, - "modrinthId": { - "type": [ - "string", - null - ], - "description": "The modrinth id of the mod.", - "pattern": "^[a-zA-Z0-9]+$" - }, - "links": { - "type": "object", - "description": "The external links a mod has.", - "properties": { - "issue": { - "type": [ - "string", - null - ], - "description": "The issue tracker link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - }, - "sourceControl": { - "type": [ - "string", - null - ], - "description": "The source control link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - }, - "others": { - "type": "array", - "description": "Other links.", - "items": { - "type": "object", - "properties": { - "linkName": { - "type": "string", - "description": "The type of link, like \"discord\", \"irc\", or \"GitHub wiki\"", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "url": { - "type": "string", - "description": "The url of the link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "required": [ - "linkName", - "url" - ] - } - } - }, - "required": [ - "issue", - "sourceControl", - "others" - ] - }, - "files": { - "type": "array", - "description": "The files the mod has.", - "items": { - "type": "object", - "properties": { - "fileName": { - "type": "string", - "description": "The name of the file.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "mcVersions": { - "type": "array", - "description": "The minecraft versions the file is compatible with. Do not include mod loaders.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - }, - "shortSha512Hash": { - "type": "string", - "description": "The short sha512 hash of the file, consisting of only 15 characters", - "pattern": "^[a-z0-9]{15}$" - }, - "downloadUrls": { - "type": "array", - "description": "The download urls of the file.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:\/?&]+$" - } - }, - "curseDownloadAvailable": { - "type": "boolean", - "description": "Whether the file is available on curseforge." - }, - "relationsToOtherMods": { - "type": "object", - "description": "The relations (i.e. dependencies/conflicts) of the file.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - }, - "required": [ - "required", - "incompatible" - ] - } - }, - "required": [ - "fileName", - "mcVersions", - "shortSha512Hash", - "downloadUrls", - "curseDownloadAvailable", - "relationsToOtherMods" - ] - } - }, - "overrides": { - "type": "object", - "description": "The manual overrides the mod has. Mostly for the maintainer's internal use", - "properties": { - "genericIdentifier": { - "type": "string", - "description": "The fancy name of the mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - }, - "fancyName": { - "type": "string", - "description": "The fancy name of the mod.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "author": { - "type": "string", - "description": "The author of the mod.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "license": { - "type": [ - "string", - null - ], - "description": "The license of the mod, or url if not a standard license.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "curseForgeId": { - "type": [ - "integer", - null - ], - "description": "The curseforge id of the mod." - }, - "modrinthId": { - "type": [ - "string", - null - ], - "description": "The modrinth id of the mod.", - "pattern": "^[a-zA-Z0-9]+$" - }, - "links": { - "type": "object", - "description": "The external links a mod has.", - "properties": { - "issue": { - "type": [ - "string", - null - ], - "description": "The issue tracker link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - }, - "sourceControl": { - "type": [ - "string", - null - ], - "description": "The source control link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - }, - "others": { - "type": "object", - "description": "Other links to override", - "properties": { - "add": { - "type": "object", - "description": "The links to add.", - "properties": { - "linkName": { - "type": "string", - "description": "The type of link, like \"discord\", \"irc\", or \"GitHub wiki\"", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "url": { - "type": "string", - "description": "The url of the link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "required": [ - "linkName", - "url" - ] - }, - "remove": { - "type": "array", - "description": "The links to remove.", - "items": { - "type": "string", - "description": "The type of link to remove, like \"discord\", \"irc\", or \"GitHub wiki\"", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - } - }, - "replace": { - "type": "object", - "description": "The links to replace.", - "properties": { - "linkName": { - "type": "string", - "description": "The type of link, like \"discord\", \"irc\", or \"GitHub wiki\"", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "url": { - "type": "string", - "description": "The url of the link.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "required": [ - "linkName", - "url" - ] - } - } - } - } - }, - "files": { - "type": "object", - "description": "The overrides for the files of the mod.", - "properties": { - "add": { - "type": "array", - "description": "The files to add for the mod.", - "items": { - "type": "object", - "properties": { - "fileName": { - "type": "string", - "description": "The name of the file.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "mcVersions": { - "type": "object", - "description": "The minecraft versions the file is compatible with.", - "properties": { - "add": { - "type": "array", - "description": "The mc versions to add.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - }, - "remove": { - "type": "array", - "description": "The mc versions to remove.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - }, - "replace": { - "type": "array", - "description": "The mc versions to replace.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - } - } - }, - "shortSha512Hash": { - "type": "string", - "description": "The short sha512 hash of the file, consisting of only 15 characters", - "pattern": "^[a-z0-9]{15}$" - }, - "downloadUrls": { - "type": "object", - "description": "The download urls of the file.", - "properties": { - "add": { - "type": "array", - "description": "The download urls to add.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "remove": { - "type": "array", - "description": "The download urls to remove.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "replace": { - "type": "array", - "description": "The download urls to replace.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - } - } - }, - "curseDownloadAvailable": { - "type": "boolean", - "description": "Whether the file is available on curseforge." - }, - "relationsToOtherMods": { - "type": "object", - "description": "The relations (i.e. dependencies/conflicts) of the file.", - "properties": { - "add": { - "type": "object", - "description": "The relations to add.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - }, - "remove": { - "type": "object", - "description": "The relations to remove.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - }, - "replace": { - "type": "object", - "description": "The relations to replace.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - } - } - } - }, - "required": [ - "fileName", - "mcVersions", - "shortSha512Hash", - "downloadUrls", - "curseDownloadAvailable", - "relationsToOtherMods" - ] - } - }, - "remove": { - "type": "array", - "description": "The files to remove.", - "items": { - "shortSha512Hash": { - "type": "string", - "description": "The short sha512 hash of the file, consisting of only 15 characters", - "pattern": "^[a-z0-9]{15}$" - } - } - }, - "replace": { - "type": "array", - "description": "The files to use instead of the original files generated", - "items": { - "type": "object", - "properties": { - "fileName": { - "type": "string", - "description": "The name of the file.", - "pattern": "^[a-zA-Z0-9\\-_\\s]+$" - }, - "mcVersions": { - "type": "object", - "description": "The minecraft versions the file is compatible with.", - "properties": { - "add": { - "type": "array", - "description": "The mc versions to add.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - }, - "remove": { - "type": "array", - "description": "The mc versions to remove.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - }, - "replace": { - "type": "array", - "description": "The mc versions to replace.", - "items": { - "type": "string", - "description": "The minecraft version. Does not include mod loaders.", - "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9\\-+._\\s]*$" - } - } - } - }, - "shortSha512Hash": { - "type": "string", - "description": "The short sha512 hash of the file, consisting of only 15 characters", - "pattern": "^[a-z0-9]{15}$" - }, - "downloadUrls": { - "type": "object", - "description": "The download urls of the file.", - "properties": { - "add": { - "type": "array", - "description": "The download urls to add.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "remove": { - "type": "array", - "description": "The download urls to remove.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - }, - "replace": { - "type": "array", - "description": "The download urls to replace.", - "items": { - "type": "string", - "description": "The download url of the file.", - "pattern": "^[a-zA-Z0-9\\-_:/?&]+$" - } - } - } - }, - "curseDownloadAvailable": { - "type": "boolean", - "description": "Whether the file is available on curseforge." - }, - "relationsToOtherMods": { - "type": "object", - "description": "The relations (i.e. dependencies/conflicts) of the file.", - "properties": { - "add": { - "type": "object", - "description": "The relations to add.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - }, - "remove": { - "type": "object", - "description": "The relations to remove.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - }, - "replace": { - "type": "object", - "description": "The relations to replace.", - "properties": { - "required": { - "type": "array", - "description": "The other mods that this mod requires to run (i.e. dependencies).", - "items": { - "type": "string", - "description": "The generic identifier of the required mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - }, - "incompatible": { - "type": "array", - "description": "The other mods that this mod is incompatible with (i.e. conflicts).", - "items": { - "type": "string", - "description": "The generic identifier of the incompatible mod.", - "pattern": "^[a-z0-9\\-_]+:[a-z0-9\\-_]+$" - } - } - } - } - } - } - }, - "required": [ - "fileName", - "mcVersions", - "shortSha512Hash", - "downloadUrls", - "curseDownloadAvailable", - "relationsToOtherMods" - ] - } - } - } - } - } - } - }, - "required": [ - "name", - "description", - "version", - "authors", - "curseForgeId", - "modrinthId", - "links", - "files" - ] -} diff --git a/schema/openapi.yaml b/schema/openapi.yaml new file mode 100644 index 00000000..44128b18 --- /dev/null +++ b/schema/openapi.yaml @@ -0,0 +1,471 @@ +openapi: "3.1.0" +info: + title: "the-mod-index" + version: "6.0.0" + description: | + The Mod Index plans to be a source where anyone can refer to for Minecraft mods, + bridging the gap between multiple major mod hosting sites. Get mod metadata, download links, and more. + + The index does **NOT** host or redistribute mod files (e.g. jars), but instead provides links/information to the mod files. + license: + name: "GNU Affero General Public License v3.0" + identifier: "AGPL-3.0" + +servers: + - url: "https://raw.githubusercontent.com/ReviversMC/the-mod-index/v6/mods" + description: "The Mod Index v6" + +components: + schemas: + indexVersion: &indexVersion + type: "string" + description: "The semver version of the targeted index." + pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+$" + example: "6.0.0" + + identifier: &identifier + type: "string" + description: "The internal identifier of the manifest available" + pattern: "^[a-z0-9\\-_]+:[a-z0-9\\-_]+:[a-z0-9]{15}$" + example: "fabric:modget:9da29a647bab8cf" + + indexForModLoader: &indexForModLoader + type: "object" + description: "The index for a specific mod loader." + properties: + indexVersion: *indexVersion + identifiers: + type: "array" + description: "The identifiers of the manifests available" + pattern: "^(?!\bindex\b|\bindices\b)[a-z0-9\\-_]+:[a-z0-9\\-_]+:[a-z0-9]{15}$" + items: *identifier + eolEpochTime: + oneOf: + - type: "integer" + description: "The epoch time when index version will no longer receive mod updates. May be larger than a 32 bit integer." + - type: "null" + description: "If the index version is still in use" + description: "The epoch time when index version will no longer receive mod updates. May be larger than a 32 bit integer." + example: "null" + required: + - "indexVersion" + - "identifiers" + - "eolEpochTime" + + modLoader: &modLoaderSchema + type: "string" + description: "The mod loader for the manifest available" + pattern: "^(?!\bindex\b|\bindices\b)[a-z0-9\\-_]+$" + example: "fabric" + + loaderModName: &loaderModNameSchema + type: "string" + description: "The given mod name for a mod in the index. Usually used in combination with the a `modLoader` to form a `genericIdentifier`" + pattern: "^[a-z0-9\\-_]+$" + example: "modget" + + shortSha512Hash: &shortSha512Hash + type: "string" + description: "A truncated sha512 hash, consisting of the first 15 characters of the lowercase hexadecimal hash" + pattern: "^[a-z0-9]{15}$" + example: "9da29a647bab8cf" + + genericIdentifier: &genericIdentifier + type: "string" + description: "The generic identifier for a mod in the index, consisting of a `modLoader` and a `loaderModName` in the format of `modLoader:loaderModName`" + pattern: "^(?!\bindex\b|\bindices\b)[a-z0-9\\-_]+:[a-z0-9\\-_]+$" + example: "fabric:modget" + + fancyName: &fancyName + type: "string" + description: "The fancy name of the mod" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" + example: "modget" + + authors: &authors + type: "array" + description: "The author(s) of the mod" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" + items: + type: "string" + description: "The author(s) of the mod" + example: "ReviversMC" + minItems: 1 + + license: &license + oneOf: + - type: "object" + description: "The license of the mod" + properties: + spdxId: + type: "string" + description: "The spdx license code of the mod" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" + example: "AGPL-3.0" + required: + - "spdxId" + - type: "object" + description: "The license of the mod" + properties: + url: + type: "string" + description: "The url of the license" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + example: "https://spdx.org/licenses/AGPL-3.0.html" + required: + - "url" + - type: "null" + description: "If the license is not available" + example: "null" + + + curseForgeId: &curseForgeId + oneOf: + - type: "integer" + description: "The curseforge id of the mod" + example: "533960" + - type: "null" + description: "If the curseforge id is not available" + example: "null" + + + modrinthId: &modrinthId + oneOf: + - type: "string" + description: "The modrinth id of the mod" + pattern: "^[a-zA-Z0-9]+$" + example: "2NpFE0R3" + - type: "null" + description: "If the modrinth id is not available" + example: "null" + + issueLink: &issueLink + oneOf: + - type: "string" + description: "The issue link for the mod" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + example: "https://github.com/ReviversMC/modget/issues/" + - type: "null" + description: "If the issue link is not available" + example: "null" + + sourceControlLink: &sourceControlLink + oneOf: + - type: "string" + description: "The source control link for the mod" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + example: "https://github.com/ReviversMC/modget/" + - type: "null" + description: "If the source control link is not available" + example: "null" + + otherLinks: &otherLinks + type: "array" + description: "Other links for the mod" + items: + type: "object" + description: "Other links for the mod" + properties: + linkName: + type: "string" + description: "The name of the link" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" + example: "Discord" + url: + type: "string" + description: "The url of the link" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + example: "https://discord.gg/6bTGYFppfz" + required: + - "linkName" + - "url" + minItems: 0 + + links: &links + type: "object" + description: "The links for the mod" + properties: + issue: *issueLink + sourceControl: *sourceControlLink + others: *otherLinks + required: + - "issue" + - "sourceControl" + - "others" + + mcVersions: &mcVersions + type: "array" + description: "The minecraft versions the mod is compatible with" + items: + type: "string" + description: "The minecraft version the mod is compatible with" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" # Don't limit to just a pattern of x.y.z, cause there are things like snapshots, pre releases, etc + example: "1.12.2, 22w24a" + minItems: 0 + + files: &files + type: "array" + description: "The files of the mod" + items: + type: "object" + description: "The file of a mod, specific to the mod loader" + properties: + fileName: + type: "string" + description: "The name of the file" + pattern: "^[a-zA-Z0-9\\-_\\s]+$" + example: "Modget 0.0.1 for MC 1.16" + mcVersions: *mcVersions + shortSha512Hash: *shortSha512Hash + downloadUrls: + type: "array" + description: "The download urls of the file, excluding CurseForge. CF links are unable to be stored due to their TOS" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + items: + type: "string" + description: "The url of the file" + pattern: "^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$" + example: "https://github.com/ReviversMC/modget-minecraft/releases/download/0.4.3/modget-minecraft-0.4.3+1.17.jar" + minItems: 0 + curseDownloadAvailable: + type: "boolean" + description: "If the file is available on CurseForge, and can be retrieved with an api call to CF" + example: "true" + relationsToOtherMods: + type: "object" + description: "The relations to other mods" + properties: + required: + type: "array" + description: | + The mods required for the mod to work (i.e. dependencies). + It is possible that there are further dependencies that are not declared here + pattern: "^(?!\bindex\b|\bindices\b)[a-z0-9\\-_]+:[a-z0-9\\-_]+$" + items: *genericIdentifier + minItems: 0 + incompatible: + type: "array" + description: | + The mods that are incompatible with the mod. + It is possible that there are further incompatibilities that are not declared here + pattern: "^(?!\bindex\b|\bindices\b)[a-z0-9\\-_]+:[a-z0-9\\-_]+$" + items: *genericIdentifier + minItems: 0 + required: + - "required" + - "incompatible" + required: + - "fileName" + - "mcVersions" + - "shortSha512Hash" + - "downloadUrls" + - "curseDownloadAvailable" + - "relationsToOtherMods" + minItems: 0 + + manifest: &manifest + type: "object" + properties: + indexVersion: *indexVersion + genericIdentifier: *genericIdentifier + fancyName: *fancyName + authors: *authors + license: *license + curseForgeId: *curseForgeId + modrinthId: *modrinthId + links: *links + files: *files + overrides: + type: "object" + description: "The overrides for the mod. Information in this field should already be reflected in the rest of the fields" + # No property should be required in overrides, as it is possible that the mod has no overrides, and there is thus no reason to send it + properties: + # Leave out index version. We do not want index version to be overrideable + + genericIdentifier: + oneOf: + - *genericIdentifier + - type: "null" + description: "If the override is not available" + example: "null" + fancyName: + oneOf: + - *fancyName + - type: "null" + description: "If the override is not available" + example: "null" + authors: + oneOf: + - *authors + - type: "null" + description: "If the override is not available" + example: "null" + license: *license # License is already nullable + curseForgeId: *curseForgeId # CurseForgeId is already nullable + modrinthId: *modrinthId # ModrinthId is already nullable + links: + oneOf: + - type: "object" + description: "If there are overrides available for links" + properties: + issues: *issueLink + sourceControl: *sourceControlLink + others: + type: "object" + description: "Other miscellaneous links to add, remove, or replace" + properties: + add: + oneOf: + - *otherLinks + - type: "null" + description: "If the override is not available" + example: "null" + remove: + oneOf: + - *otherLinks + - type: "null" + description: "If the override is not available" + example: "null" + replace: + oneOf: + - *otherLinks + - type: "null" + description: "If the override is not available" + example: "null" + - type: "null" + description: "If there are no overrides available for links" + example: "null" + + files: + oneOf: + - type: "object" + description: "Files to add, remove, or replace. Edit a file by removing it and adding it again" + properties: + add: + oneOf: + - *files + - type: "null" + description: "If the override is not available" + example: "null" + remove: + oneOf: + - *files + - type: "null" + description: "If the override is not available" + example: "null" + replace: + oneOf: + - *files + - type: "null" + description: "If the override is not available" + example: "null" + - type: "null" + description: "If there are no overrides available for files" + example: "null" + + required: + - "indexVersion" + - "genericIdentifier" + - "fancyName" + - "authors" + - "license" + - "curseForgeId" + - "modrinthId" + - "links" + - "files" + # Do not make overrides required. If not present, the entire field should be omitted + + parameters: + modLoaderParam: &modLoaderParam + name: "modLoader" + in: "path" + description: "The mod loader for which to get the index" + required: "true" + schema: *modLoaderSchema + + loaderModNameParam: &loaderModNameParam + name: "loaderModName" + in: "path" + description: "The given mod name for a mod in the index. Usually used in combination with the a `modLoader` to form a `genericIdentifier`" + required: "true" + schema: *loaderModNameSchema + +tags: + - name: "indexFiles" + x-displayName: "Index Files" + description: "The index files to navigate \"the-mod-index\"" + - name: "manifestFiles" + x-displayName: "Manifest Files" + description: "The manifest files found in \"the-mod-index\"" + +paths: + /indices/index.json: + get: + operationId: "getIndex" + summary: "Get the index for all mod loaders." + description: "Get the index for all mod loaders. Does not include similar mods from other mod loaders." + tags: + - "indexFiles" + responses: + 200: + description: "Expected response to a valid request" + content: + application/json: + schema: + allOf: + - *indexForModLoader + - type: "object" + properties: + modLoaders: + type: "array" + description: "The mod loaders that are available" + items: *modLoaderSchema + required: + - "modLoaders" + + 404: + description: "The page was not found" + + # {modLoader} in the path to explicitly exclude `index` as a result, as `index.json` redirects to `/indices/index.json`. + /indices/{modLoader}.json: + get: + operationId: "getLoaderIndex" + summary: "Get the index for a specific mod loader." + description: "Get the index for a specific mod loader. Does not include similar mods from other mod loaders." + tags: + - "indexFiles" + parameters: + - *modLoaderParam + responses: + 200: + description: "Expected response to a valid request" + content: + application/json: + schema: *indexForModLoader + 404: + description: "The page was not found" + + /{modLoader}/{loaderModName}.json: + get: + operationId: "getModManifest" + summary: "Get the manifest for a specific mod." + description: | + Get the manifest for a specific mod. + Only returns valid information for the mod loader specified in the path, not all information for the mod + + For example, in a mod which has separate Fabric and Forge files, should {modLoader} be `forge`, + only the Forge files will be reflected in the Forge manifest + tags: + - "manifestFiles" + parameters: + - *modLoaderParam + - *loaderModNameParam + responses: + 200: + description: "Expected response to a valid request" + content: + application/json: + schema: *manifest + 404: + description: "The page was not found" + From 366596995e87c109c0837f918baa3dbab8ee1bc6 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 12:23:42 -0700 Subject: [PATCH 02/18] update index file --- mods/index.json | 5 ----- mods/indices/index.json | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 mods/index.json create mode 100644 mods/indices/index.json diff --git a/mods/index.json b/mods/index.json deleted file mode 100644 index 693d0b9e..00000000 --- a/mods/index.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "indexVersion": "5.2.0", - "identifiers": [], - "eolEpochTime": null -} diff --git a/mods/indices/index.json b/mods/indices/index.json new file mode 100644 index 00000000..dab5011a --- /dev/null +++ b/mods/indices/index.json @@ -0,0 +1 @@ +{"indexVersion":"5.2.0","modLoaders":[],"identifiers":[],"eolEpochTime":null} \ No newline at end of file From c1078f4df20ee361ccd76b07b6de8643b47afc0f Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 14:40:45 -0700 Subject: [PATCH 03/18] Add deploy action to spec update --- .github/workflows/pages.yaml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/pages.yaml diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml new file mode 100644 index 00000000..f5e1f4a0 --- /dev/null +++ b/.github/workflows/pages.yaml @@ -0,0 +1,32 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy TMI spec + +on: + # Runs on pushes targeting the default branch and spec update branches + push: + branches: ["v5", "spec-update/*"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: write +jobs: + build-and-deploy: + concurrency: ci-${{ github.ref }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build pages + run: | + npm i -g redoc-cli + redoc-cli build schema/openapi.yaml + mkdir build/ + mv redoc-static.html build/index.html + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: build + target-folder: ${{ github.ref }} # Publish docs to a specific path. This allows spec updates to not override existing prod sites From 7c19b8f3fe1b067dd9eed5d5332ff236a6d5f39b Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 14:44:27 -0700 Subject: [PATCH 04/18] Use ref name instead of ref --- .github/workflows/pages.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index f5e1f4a0..5ab96c6e 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -29,4 +29,4 @@ jobs: uses: JamesIves/github-pages-deploy-action@v4 with: folder: build - target-folder: ${{ github.ref }} # Publish docs to a specific path. This allows spec updates to not override existing prod sites + target-folder: ${{ github.ref_name }} # Publish docs to a specific path. This allows spec updates to not override existing prod sites From 8b8ab55e6e16c3490a5700254b3f22bbefca944c Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 14:59:18 -0700 Subject: [PATCH 05/18] Attempt exclude spec update branches from json check --- .github/workflows/jsonCheck.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index bdb3b877..2d062b28 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -7,6 +7,7 @@ on: branches: [ v5 ] jobs: + if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false build: runs-on: ubuntu-latest steps: From c5d151300e0e9dda8220be3e96113c6e24a21fdd Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:10:34 -0700 Subject: [PATCH 06/18] Attempt exclude spec update branches from json check (2) --- .github/workflows/jsonCheck.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 2d062b28..60dc3f17 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -1,13 +1,16 @@ -name: Json Check +name: Check json in index on: push: - branches: [ v5, maintainer-test ] + branches: + - v5 + - maintainer-test + - !spec-update/* pull_request: - branches: [ v5 ] + branches: + - v5 jobs: - if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false build: runs-on: ubuntu-latest steps: From 8aa676d9b5641e8a2af60aea920e9dce82ac2610 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:13:40 -0700 Subject: [PATCH 07/18] Attempt exclude spec update branches from json check (3) --- .github/workflows/jsonCheck.yaml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 60dc3f17..9d189e1f 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -2,17 +2,14 @@ name: Check json in index on: push: - branches: - - v5 - - maintainer-test - - !spec-update/* + branches: [ v5, maintainer-test ] pull_request: - branches: - - v5 + branches: [ v5 ] jobs: build: runs-on: ubuntu-latest + if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false steps: - name: Do the checking of index and manifest files uses: reviversmc/the-mod-index-validation@latest \ No newline at end of file From 36b955e214cd5e85f945485abf77ae39e56f0567 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:19:52 -0700 Subject: [PATCH 08/18] Attempt exclude spec update branches from json check (4) --- .github/workflows/jsonCheck.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 9d189e1f..180e1e6b 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -7,9 +7,9 @@ on: branches: [ v5 ] jobs: - build: + validate: + if: github.ref != "refs/heads/spec-update/*" runs-on: ubuntu-latest - if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false steps: - name: Do the checking of index and manifest files uses: reviversmc/the-mod-index-validation@latest \ No newline at end of file From fb587c91058ca8e5b74854b2e269dbed0ca9163d Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:20:42 -0700 Subject: [PATCH 09/18] Attempt exclude spec update branches from json check (5) --- .github/workflows/jsonCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 180e1e6b..92e07e34 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -8,7 +8,7 @@ on: jobs: validate: - if: github.ref != "refs/heads/spec-update/*" + if: ${{ github.ref }} != "refs/heads/spec-update/*" runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From da827dd475b85ae43839e0958a1319a7749d3716 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:22:13 -0700 Subject: [PATCH 10/18] Attempt exclude spec update branches from json check (6) --- .github/workflows/jsonCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 92e07e34..66d3a072 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -8,7 +8,7 @@ on: jobs: validate: - if: ${{ github.ref }} != "refs/heads/spec-update/*" + if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 48cb45008a8863bb23499516fc03d66c8caa579f Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:25:30 -0700 Subject: [PATCH 11/18] Attempt exclude spec update branches from json check (7) --- .github/workflows/jsonCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 66d3a072..658120c6 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -8,7 +8,7 @@ on: jobs: validate: - if: startsWith(${{ github.ref }}, "refs/heads/spec-update/") == false + if: ${{ startsWith(github.ref, "refs/heads/spec-update/") == false }} runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 202d15ee1460dad12d51401ca70b73baccdaf41c Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:26:34 -0700 Subject: [PATCH 12/18] Attempt exclude spec update branches from json check (8) --- .github/workflows/jsonCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 658120c6..51b336fc 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -8,7 +8,7 @@ on: jobs: validate: - if: ${{ startsWith(github.ref, "refs/heads/spec-update/") == false }} + if: ${{ github.ref != 'refs/heads/spec-update/*' }} runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 47e46caf8cb70524c12fbd8157220aba6b4d36c3 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:32:41 -0700 Subject: [PATCH 13/18] Attempt exclude spec update branches from json check (9) --- .github/workflows/jsonCheck.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 51b336fc..53483176 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -2,13 +2,17 @@ name: Check json in index on: push: - branches: [ v5, maintainer-test ] + branches: + - v5 + - maintainer-test pull_request: - branches: [ v5 ] + branches: + - v5 + branches-ignore: + - refs/heads/spec-update/* jobs: validate: - if: ${{ github.ref != 'refs/heads/spec-update/*' }} runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 0f795f7cfb1158f18264f803016bbdc036a93962 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:35:16 -0700 Subject: [PATCH 14/18] Attempt exclude spec update branches from json check (10) --- .github/workflows/jsonCheck.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 53483176..caf53e40 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -8,11 +8,10 @@ on: pull_request: branches: - v5 - branches-ignore: - - refs/heads/spec-update/* jobs: validate: + if: github.ref != "refs/heads/spec-update/*" runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 6c8cbc981f6d7b476d2f29c1e256d16bab572317 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:35:48 -0700 Subject: [PATCH 15/18] Attempt exclude spec update branches from json check (11) --- .github/workflows/jsonCheck.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index caf53e40..f19c9d3e 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -11,7 +11,7 @@ on: jobs: validate: - if: github.ref != "refs/heads/spec-update/*" + if: github.ref != 'refs/heads/spec-update/*' runs-on: ubuntu-latest steps: - name: Do the checking of index and manifest files From 0a6d840ab029f51cd755d2ae2468a956ee9f02f7 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:37:56 -0700 Subject: [PATCH 16/18] Attempt exclude spec update branches from json check (12) --- .github/workflows/jsonCheck.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index f19c9d3e..7f772c53 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -11,8 +11,8 @@ on: jobs: validate: - if: github.ref != 'refs/heads/spec-update/*' + if: github.ref != 'refs/heads/spec-update/[0-9]+.[0-9]+.[0-9]+' runs-on: ubuntu-latest steps: - - name: Do the checking of index and manifest files + - name: Check index and manifest files uses: reviversmc/the-mod-index-validation@latest \ No newline at end of file From 6d4047a85bb0fe384fca633819e31d2610c02a0d Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Sat, 13 Aug 2022 15:40:51 -0700 Subject: [PATCH 17/18] Perhaps it's not all that bad to have json checked - just update validator to read openapi file instead --- .github/workflows/jsonCheck.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/jsonCheck.yaml b/.github/workflows/jsonCheck.yaml index 7f772c53..78881708 100644 --- a/.github/workflows/jsonCheck.yaml +++ b/.github/workflows/jsonCheck.yaml @@ -11,8 +11,7 @@ on: jobs: validate: - if: github.ref != 'refs/heads/spec-update/[0-9]+.[0-9]+.[0-9]+' runs-on: ubuntu-latest steps: - name: Check index and manifest files - uses: reviversmc/the-mod-index-validation@latest \ No newline at end of file + uses: ReviversMC/the-mod-index-validation@latest From 2a6fb4a7c737d63d4f8cf35d985192f2434ec169 Mon Sep 17 00:00:00 2001 From: Cloudate9 <65006925+Cloudate9@users.noreply.github.com> Date: Mon, 15 Aug 2022 14:20:07 -0700 Subject: [PATCH 18/18] Add eof --- mods/indices/index.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/indices/index.json b/mods/indices/index.json index dab5011a..5244fd60 100644 --- a/mods/indices/index.json +++ b/mods/indices/index.json @@ -1 +1 @@ -{"indexVersion":"5.2.0","modLoaders":[],"identifiers":[],"eolEpochTime":null} \ No newline at end of file +{"indexVersion":"5.2.0","modLoaders":[],"identifiers":[],"eolEpochTime":null}