diff --git a/public/manifest.schema.json b/public/manifest.schema.json new file mode 100644 index 0000000..84f726f --- /dev/null +++ b/public/manifest.schema.json @@ -0,0 +1,355 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "https://moonlight-mod.github.io/manifest.schema.json", + "title": "Extension manifest", + "description": "A moonlight extension manifest", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for your extension" + }, + "version": { + "type": "string", + "description": "Version of your extension, needed for publishing" + }, + "apiLevel": { + "type": "integer", + "exclusiveMinimum": 0, + "description": "API level this extension targets, if it does not match the current version, the extension will not be loaded" + }, + "environment": { + "description": "Which environment this extension is capable of running in", + "oneOf": [ + { "const": "both", "description": "Extension will run on both platforms, the host/native modules MAY be loaded" }, + { "const": "desktop", "description": "Extension will run on desktop only, the host/native modules are guaranteed to load" }, + { "const": "web", "description": "Equivilant to both" } + ] + }, + "meta": { + "$ref": "#/definitions/metadata" + }, + "dependencies": { + "type": "array", + "description": "List of extensions identifiers that this extension depends on", + "items": { + "type": "string" + } + }, + "suggested": { + "type": "array", + "description": "List of extensions identifiers that this extension suggests using", + "items": { + "type": "string" + } + }, + "incompatible": { + "type": "array", + "description": "List of extensions identifiers that this extension is incompatible with", + "items": { + "type": "string" + } + }, + "settings": { + "$ref": "#/definitions/settings" + }, + "cors": { + "type": "array", + "description": "List of URLs that should have CORS bypassed", + "items": { + "type": "string", + "format": "uri" + } + }, + "blocked": { + "type": "array", + "description": "List of URL match patterns for which requests should be blocked", + "items": { + "type": "string", + "format": "uri" + } + } + }, + "additionalProperties": false, + "required": ["id", "apiLevel"], + "definitions": { + "metadata": { + "type": "object", + "description": "Purely visual metadata", + "properties": { + "name": { + "type": "string", + "description": "A user-readable display name for your extension" + }, + "tagline": { + "type": "string", + "description": "A short string displayed beneath the extension's name" + }, + "description": { + "type": "string", + "description": "A long-form description visible in a separate tab" + }, + "authors": { + "type": "array", + "description": "Authors involved in the creation of this extension", + "items": { + "$ref": "#/definitions/author" + } + }, + "deprecated": { + "type": "boolean" + }, + "tags": { + "type": "array", + "description": "List of tags the extension is part of", + "items": { + "$ref": "#/definitions/tag" + } + }, + "source": { + "type": "string" + } + } + }, + "author": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the author" + }, + "id": { + "type": "string", + "description": "The user ID of the corresponding user" + } + }, + "required": ["name"] + } + ] + }, + "tag": { + "enum": [ + "accessibility", + "appearance", + "chat", + "commands", + "contextMenu", + "dangerZone", + "development", + "fixes", + "fun", + "markdown", + "voice", + "privacy", + "profiles", + "qol", + "library" + ] + }, + "settings": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": ["type"], + "properties": { + "type": { + "$ref": "#/definitions/settings/definitions/type" + }, + "displayName": { + "type": "string", + "description": "User-facing name of the setting" + }, + "description": { + "type": "string", + "description": "A short description of the setting's purpose" + } + }, + "allOf": [ + { + "if": { "properties": { "type": { "const": "boolean" } } }, + "then": { "$ref": "#/definitions/settings/definitions/boolean" } + }, + { + "if": { "properties": { "type": { "const": "number" } } }, + "then": { "$ref": "#/definitions/settings/definitions/number" } + }, + { + "if": { "properties": { "type": { "const": "string" } } }, + "then": { "$ref": "#/definitions/settings/definitions/string" } + }, + { + "if": { "properties": { "type": { "const": "multilinestring" } } }, + "then": { + "$ref": "#/definitions/settings/definitions/multilinestring" + } + }, + { + "if": { "properties": { "type": { "const": "select" } } }, + "then": { "$ref": "#/definitions/settings/definitions/select" } + }, + { + "if": { "properties": { "type": { "const": "multiselect" } } }, + "then": { "$ref": "#/definitions/settings/definitions/multiselect" } + }, + { + "if": { "properties": { "type": { "const": "list" } } }, + "then": { "$ref": "#/definitions/settings/definitions/list" } + }, + { + "if": { "properties": { "type": { "const": "dictionary" } } }, + "then": { "$ref": "#/definitions/settings/definitions/dictionary" } + }, + { + "if": { "properties": { "type": { "const": "custom" } } }, + "then": { "$ref": "#/definitions/settings/definitions/custom" } + } + ] + }, + "definitions": { + "type": { + "oneOf": [ + { + "const": "boolean", + "description": "A simple switch" + }, + { + "const": "number", + "description": "Number field" + }, + { + "const": "string", + "description": "String input field" + }, + { + "const": "multilinestring", + "description": "String input that allows multiple lines" + }, + { + "const": "select", + "description": "Selection between one of multiple values" + }, + { + "const": "multiselect", + "description": "Selection of multiple values" + }, + { + "const": "multiselect", + "description": "Selection of multiple values" + }, + { + "const": "list", + "description": "List of strings defined by the user" + }, + { + "const": "dictionary", + "description": "Mapping of strings defined by the user" + }, + { + "const": "custom", + "description": "Custom settings component, currently not implemented" + } + ] + }, + "boolean": { + "required": ["type"], + "properties": { + "default": { "type": "boolean" } + } + }, + "number": { + "required": ["type"], + "properties": { + "default": { "type": "number" }, + "min": { "type": "number" }, + "max": { "type": "number" } + } + }, + "string": { + "required": ["type"], + "properties": { + "default": { "type": "string" } + } + }, + "multilinestring": { + "required": ["type"], + "properties": { + "default": { "type": "string" } + } + }, + "select": { + "required": ["type", "options"], + "properties": { + "options": { + "oneOf": [ + { "type": "string" }, + { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": ["label", "value"] + } + ] + }, + "default": { "type": "string" } + } + }, + "multiselect": { + "required": ["type", "options"], + "properties": { + "options": { + "type": "array", + "items": { + "type": "string" + } + }, + "default": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "list": { + "required": ["type"], + "properties": { + "default": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "dictionary": { + "required": ["type"], + "properties": { + "default": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "custom": { + "required": ["type"], + "properties": { + "default": {} + } + } + } + } + } +}