{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://github.com/pulumi/pulumi/blob/master/pkg/codegen/schema.json",
    "title": "Pulumi Package Metaschema",
    "description": "A description of the schema for a Pulumi Package",
    "type": "object",
    "properties": {
        "name": {
            "description": "The unqualified name of the package (e.g. \"aws\", \"azure\", \"gcp\", \"kubernetes\", \"random\")",
            "type": "string",
            "pattern": "^[a-zA-Z][-a-zA-Z0-9_]*$"
        },
        "displayName": {
            "description": "The human-friendly name of the package.",
            "type": "string"
        },
        "version": {
            "description": "The version of the package. The version must be valid semver.",
            "type": "string",
            "pattern": "^v?(?P<major>0|[1-9]\\d*)\\.(?P<minor>0|[1-9]\\d*)\\.(?P<patch>0|[1-9]\\d*)(?:-(?P<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
        },
        "description": {
            "description": "The description of the package. Descriptions are interpreted as Markdown.",
            "type": "string"
        },
        "keywords": {
            "description": "The list of keywords that are associated with the package, if any.",
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "homepage": {
            "description": "The package's homepage.",
            "type": "string"
        },
        "license": {
            "description": "The name of the license used for the package's contents.",
            "type": "string"
        },
        "attribution": {
            "description": "Freeform text attribution of derived work, if required.",
            "type": "string"
        },
        "repository": {
            "description": "The URL at which the package's sources can be found.",
            "type": "string"
        },
        "logoUrl": {
            "description": "The URL of the package's logo, if any.",
            "type": "string"
        },
        "pluginDownloadUrl": {
            "description": "The URL to use when downloading the provider plugin binary.",
            "type": "string"
        },
        "publisher": {
            "description": "The name of the person or organization that authored and published the package.",
            "type": "string"
        },
        "meta": {
            "description": "Format metadata about this package.",
            "type": "object",
            "properties": {
                "moduleFormat": {
                    "description": "A regex that is used by the importer to extract a module name from the module portion of a type token. Packages that use the module format \"namespace1/namespace2/.../namespaceN\" do not need to specify a format. The regex must define one capturing group that contains the module name, which must be formatted as \"namespace1/namespace2/...namespaceN\".",
                    "type": "string",
                    "format": "regex"
                }
            },
            "required": ["moduleFormat"]
        },
        "config": {
            "description": "The package's configuration variables.",
            "type": "object",
            "properties": {
                "variables": {
                    "description": "A map from variable name to propertySpec that describes a package's configuration variables.",
                    "type": "object",
                    "additionalProperties": {
                        "$ref": "#/$defs/propertySpec"
                    }
                },
                "required": {
                    "description": "A list of the names of the package's required configuration variables.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        },
        "types": {
            "description": "A map from type token to complexTypeSpec that describes the set of complex types (i.e. object, enum) defined by this package.",
            "type": "object",
            "additionalProperties": {
                "$ref": "#/$defs/complexTypeSpec"
            },
            "propertyNames": {
                "$ref": "#/$defs/token"
            }
        },
        "provider": {
            "description": "The provider type for this package.",
            "$ref": "#/$defs/resourceSpec"
        },
        "resources": {
            "description": "A map from type token to resourceSpec that describes the set of resources and components defined by this package.",
            "type": "object",
            "additionalProperties": {
                "$ref": "#/$defs/resourceSpec"
            },
            "propertyNames": {
                "$ref": "#/$defs/token"
            }
        },
        "functions": {
            "description": "A map from token to functionSpec that describes the set of functions defined by this package.",
            "type": "object",
            "additionalProperties": {
                "$ref": "#/$defs/functionSpec"
            },
            "propertyNames": {
                "$ref": "#/$defs/token"
            }
        },
        "language": {
            "description": "Additional language-specific data about the package.",
            "type": "object"
        }
    },
    "additionalProperties": false,
    "required": [
        "name"
    ],
    "$defs": {
        "token": {
            "title": "Token",
            "type": "string",
            "$comment": "In the regex below, the 'module' portion of the token is optional. However, a missing module component creates a '::', which breaks URNs ('::' is the URN delimiter). We have many test schemas that use an empty module component successfully, as they never create URNs; while these are _probably_ the only places that need updating, it might be possible that there are module-less type tokens in the wild elsewhere and we may need to remain compatible with those tokens.",
            "pattern": "^[a-zA-Z][-a-zA-Z0-9_]*:([^0-9][a-zA-Z0-9._/-]*)?:[^0-9][a-zA-Z0-9._/]*$"
        },
        "typeSpec": {
            "title": "Type Reference",
            "description": "A reference to a type. The particular kind of type referenced is determined based on the contents of the \"type\" property and the presence or absence of the \"additionalProperties\", \"items\", \"oneOf\", and \"$ref\" properties.",
            "type": "object",
            "properties": {
                "plain": {
                    "description": "Indicates that when used as an input, this type does not accept eventual values.",
                    "type": "boolean"
                }
            },
            "oneOf": [
                {
                    "title": "Primitive Type",
                    "description": "A reference to a primitive type. A primitive type must have only the \"type\" property set.",
                    "type": "object",
                    "properties": {
                        "type": {
                            "description": "The primitive type, if any",
                            "type": "string",
                            "enum": ["boolean", "integer", "number", "string"]
                        },
                        "additionalProperties": false,
                        "items": false,
                        "oneOf": false,
                        "$ref": false
                    },
                    "required": ["type"]
                },
                {
                    "title": "Array Type",
                    "description": "A reference to an array type. The \"type\" property must be set to \"array\" and the \"items\" property must be present. No other properties may be present.",
                    "type": "object",
                    "$comment": "An array type must have the \"type\" property set.",
                    "properties": {
                        "type": {
                            "const": "array"
                        },
                        "items": {
                            "description": "The element type of the array",
                            "$ref": "#/$defs/typeSpec"
                        },
                        "additionalProperties": false,
                        "oneOf": false,
                        "$ref": false
                    },
                    "required": ["type", "items"]
                },
                {
                    "title": "Map Type",
                    "description": "A reference to a map type. The \"type\" property must be set to \"object\" and the \"additionalProperties\" property may be present. No other properties may be present.",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "object"
                        },
                        "additionalProperties": {
                            "description": "The element type of the map. Defaults to \"string\" when omitted.",
                            "$ref": "#/$defs/typeSpec"
                        },
                        "items": false,
                        "oneOf": false,
                        "$ref": false
                    },
                    "required": ["type"]
                },
                {
                    "title": "Named Type",
                    "description": "A reference to a type in this or another document. The \"$ref\" property must be present. The \"type\" property is ignored if it is present. No other properties may be present.",
                    "type": "object",
                    "properties": {
                        "type": {
                            "description": "ignored; present for compatibility with existing schemas",
                            "type": "string"
                        },
                        "$ref": {
                            "description": "The URI of the referenced type. For example, the built-in Archive, Asset, and Any\ntypes are referenced as \"pulumi.json#/Archive\", \"pulumi.json#/Asset\", and \"pulumi.json#/Any\", respectively.\nA type from this document is referenced as \"#/types/pulumi:type:token\".\nA type from another document is referenced as \"path#/types/pulumi:type:token\", where path is of the form:\n  \"/provider/vX.Y.Z/schema.json\" or \"pulumi.json\" or \"http[s]://example.com/provider/vX.Y.Z/schema.json\"\nA resource from this document is referenced as \"#/resources/pulumi:type:token\".\nA resource from another document is referenced as \"path#/resources/pulumi:type:token\", where path is of the form:\n  \"/provider/vX.Y.Z/schema.json\" or \"pulumi.json\" or \"http[s]://example.com/provider/vX.Y.Z/schema.json\"",
                            "type": "string",
                            "format": "uri-reference"
                        },
                        "additionalProperties": false,
                        "items": false,
                        "oneOf": false
                    },
                    "required": ["$ref"]
                },
                {
                    "title": "Union Type",
                    "description": "A reference to a union type. The \"oneOf\" property must be present. The union may additional specify an underlying primitive type via the \"type\" property and a discriminator via the \"discriminator\" property. No other properties may be present.",
                    "type": "object",
                    "properties": {
                        "type": {
                            "description": "The underlying primitive type of the union, if any",
                            "type": "string",
                            "enum": ["boolean", "integer", "number", "string"]
                        },
                        "oneOf": {
                            "description": "If present, indicates that values of the type may be one of any of the listed types",
                            "type": "array",
                            "items": {
                                "$ref": "#/$defs/typeSpec"
                            },
                            "minItems": 2
                        },
                        "discriminator": {
                            "description": "Informs the consumer of an alternative schema based on the value associated with it",
                            "type": "object",
                            "properties": {
                                "propertyName": {
                                    "description": "PropertyName is the name of the property in the payload that will hold the discriminator value",
                                    "type": "string",
                                    "minLength": 1
                                },
                                "mapping": {
                                    "description": "an optional object to hold mappings between payload values and schema names or references",
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            },
                            "required": [
                                "propertyName"
                            ]
                        },
                        "additionalProperties": false,
                        "items": false,
                        "$ref": false
                    },
                    "required": ["oneOf"]
                }
            ]
        },
        "propertySpec": {
            "title": "Property Definition",
            "description": "Describes an object or resource property",
            "type": "object",
            "allOf": [
                { "$ref": "#/$defs/typeSpec" }
            ],
            "properties": {
                "description": {
                    "description": "The description of the property, if any. Interpreted as Markdown.",
                    "type": "string"
                },
                "const": {
                    "description": "The constant value for the property, if any. The type of the value must be assignable to the type of the property.",
                    "type": ["boolean", "number", "string"]
                },
                "default": {
                    "description": "The default value for the property, if any. The type of the value must be assignable to the type of the property.",
                    "type": ["boolean", "number", "string"]
                },
                "defaultInfo": {
                    "description": "Additional information about the property's default value, if any.",
                    "type": "object",
                    "properties": {
                        "environment": {
                            "description": "A set of environment variables to probe for a default value.",
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        },
                        "language": {
                            "description": "Additional language-specific data about the default value.",
                            "type": "object"
                        }
                    },
                    "required": ["environment"]
                },
                "deprecationMessage": {
                    "description": "Indicates whether the property is deprecated",
                    "type": "string"
                },
                "language": {
                    "description": "Additional language-specific data about the property.",
                    "type": "object"
                },
                "secret": {
                    "description": "Specifies whether the property is secret (default false).",
                    "type": "boolean"
                },
                "replaceOnChanges": {
                    "description": "Specifies whether a change to the property causes its containing resource to be replaced instead of updated (default false).",
                    "type": "boolean"
                }
            }
        },
        "complexTypeSpec": {
            "title": "Type Definition",
            "description": "Describes an object or enum type.",
            "type": "object",
            "properties": {
                "description": {
                    "description": "The description of the type, if any. Interpreted as Markdown.",
                    "type": "string"
                },
                "language": {
                    "description": "Additional language-specific data about the type.",
                    "type": "object"
                },
                "isOverlay": {
                    "description": "Indicates that the implementation of the type should not be generated from the schema, and is instead provided out-of-band by the package author",
                    "type": "boolean"
                }
            },
            "oneOf": [
                {
                    "title": "Object Type Definition",
                    "type": "object",
                    "allOf": [
                        { "$ref": "#/$defs/objectTypeSpec" }
                    ],
                    "properties": {
                        "type": {
                            "const": "object"
                        }
                    }
                },
                { "$ref": "#/$defs/enumTypeSpec" }
            ]
        },
        "objectTypeSpec": {
            "title": "Object Type Details",
            "description": "Describes an object type",
            "type": "object",
            "properties": {
                "properties": {
                    "description": "A map from property name to propertySpec that describes the object's properties.",
                    "type": "object",
                    "additionalProperties": {
                        "$ref": "#/$defs/propertySpec"
                    }
                },
                "required": {
                    "description": "A list of the names of an object type's required properties. These properties must be set for inputs and will always be set for outputs.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        },
        "enumTypeSpec": {
            "title": "Enum Type Definition",
            "description": "Describes an enum type",
            "type": "object",
            "properties" :{
                "type": {
                    "description": "The underlying primitive type of the enum",
                    "type": "string",
                    "enum": ["boolean", "integer", "number", "string"]
                },
                "enum": {
                    "description": "The list of possible values for the enum",
                    "type": "array",
                    "items": {
                        "title": "Enum Value Definition",
                        "type": "object",
                        "properties": {
                            "name": {
                                "description": "If present, overrides the name of the enum value that would usually be derived from the value.",
                                "type": "string"
                            },
                            "description": {
                                "description": "The description of the enum value, if any. Interpreted as Markdown.",
                                "type": "string"
                            },
                            "value": {
                                "description": "The enum value itself",
                                "type": ["boolean", "integer", "number", "string"]
                            },
                            "deprecationMessage": {
                                "description": "Indicates whether the value is deprecated.",
                                "type": "string"
                            }
                        },
                        "required": ["value"]
                    }
                }
            },
            "required": ["type", "enum"]
        },
        "resourceSpec": {
            "title": "Resource Definition",
            "description": "Describes a resource or component.",
            "type": "object",
            "allOf": [
                { "$ref": "#/$defs/objectTypeSpec" }
            ],
            "properties": {
                "description": {
                    "description": "The description of the resource, if any. Interpreted as Markdown.",
                    "type": "string"
                },
                "inputProperties": {
                    "description": "A map from property name to propertySpec that describes the resource's input properties.",
                    "type": "object",
                    "additionalProperties": {
                        "$ref": "#/$defs/propertySpec"
                    }
                },
                "requiredInputs": {
                    "description": "A list of the names of the resource's required input properties.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "stateInputs": {
                    "description": "An optional objectTypeSpec that describes additional inputs that mau be necessary to get an existing resource. If this is unset, only an ID is necessary.",
                    "$ref": "#/$defs/objectTypeSpec"
                },
                "aliases": {
                    "description": "The list of aliases for the resource.",
                    "type": "array",
                    "items": {
                        "title": "Alias Definition",
                        "type": "object",
                        "properties": {
                            "name": {
                                "description": "The name portion of the alias, if any",
                                "type": "string"
                            },
                            "project": {
                                "description": "The project portion of the alias, if any",
                                "type": "string"
                            },
                            "type": {
                                "description": "The type portion of the alias, if any",
                                "type": "string"
                            }
                        }
                    }
                },
                "deprecationMessage": {
                    "description": "Indicates whether the resource is deprecated",
                    "type": "string"
                },
                "isComponent": {
                    "description": "Indicates whether the resource is a component.",
                    "type": "boolean"
                },
                "methods": {
                    "description": "A map from method name to function token that describes the resource's method set.",
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "isOverlay": {
                    "description": "Indicates that the implementation of the resource should not be generated from the schema, and is instead provided out-of-band by the package author",
                    "type": "boolean"
                }
            }
        },
        "functionSpec": {
            "title": "Function Definition",
            "description": "Describes a function.",
            "type": "object",
            "properties": {
                "description": {
                    "description": "The description of the function, if any. Interpreted as Markdown.",
                    "type": "string"
                },
                "inputs": {
                    "description": "The bag of input values for the function, if any.",
                    "$ref": "#/$defs/objectTypeSpec"
                },
                "outputs": {
                    "description": "The bag of output values for the function, if any.",
                    "$ref": "#/$defs/objectTypeSpec"
                },
                "deprecationMessage": {
                    "description": "Indicates whether the function is deprecated",
                    "type": "string"
                },
                "language": {
                    "description": "Additional language-specific data about the function.",
                    "type": "object"
                },
                "isOverlay": {
                    "description": "Indicates that the implementation of the function should not be generated from the schema, and is instead provided out-of-band by the package author",
                    "type": "boolean"
                }
            }
        }
    }
}
