{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "additionalProperties": false,
  "definitions": {
    "moveItems": {
      "type": "object",
      "required": ["to", "names"],
      "properties": {
        "to": {
          "type": "string",
          "description": "The path to move the directory to"
        },
        "names": {
          "type": "array",
          "items": {
            "type": "string",
            "description": "The directories to move"
          }
        }
      }
    },
    "mergeJson": {
      "description": "Merge json file with jq command line tool pattern matching",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "description": "Merge type",
          "enum": ["jq"]
        },
        "path": {
          "type": "string",
          "description": "Path to file to merge"
        },
        "replace": {
          "type": "array",
          "description": "JQ pattern of property to replace",
          "items": {
            "type": "string"
          }
        },
        "create": {
          "type": "array",
          "description": "JQ pattern of property to create if the property does not exist in target project file",
          "items": {
            "type": "string"
          }
        },
        "replaceIf": {
          "type": "array",
          "description": "A set of properties to replace if the condition evaluates to truthy",
          "items": {
            "type": "object",
            "description": "Configuration for property to replace if condition evaluates to truthy",
            "required": ["condition", "pattern"],
            "properties": {
              "condition": {
                "type": "string",
                "description": "The condition to evaluate for truthiness. If truthy will replace property matched by pattern"
              },
              "pattern": {
                "type": "string",
                "description": "JQ pattern of property to replace"
              }
            }
          }
        },
        "set": {
          "type": "object",
          "description": "Set the value of these items to the value. So `'.license':MIT` would set the `license` property of the json file to 'MIT'",
          "additionalProperties": {
            "type": "string"
          }
        },
        "skip": {
          "type": "array",
          "description": "A list of items to not create, copy, replace, or remove in target file",
          "items": {
            "type": "string"
          }
        },
        "skipIfNotSameFileName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "mergeYaml": {
      "description": "Merge yaml file with yq command line tool pattern matching",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "description": "Merge type",
          "enum": ["yq"]
        },
        "path": {
          "type": "string",
          "description": "Path to file to merge"
        },
        "replace": {
          "type": "array",
          "description": "YQ pattern of property to replace",
          "items": {
            "type": "string"
          }
        },
        "create": {
          "type": "array",
          "description": "YQ pattern of property to create if the property does not exist in target project file",
          "items": {
            "type": "string"
          }
        },
        "replaceIf": {
          "type": "array",
          "description": "A set of properties to replace if the condition evaluates to truthy",
          "items": {
            "type": "object",
            "description": "Configuration for property to replace if condition evaluates to truthy",
            "required": ["condition", "pattern"],
            "properties": {
              "condition": {
                "type": "string",
                "description": "The condition to evaluate for truthiness. If truthy will replace property matched by pattern"
              },
              "pattern": {
                "type": "string",
                "description": "YQ pattern of property to replace"
              }
            }
          }
        },
        "set": {
          "type": "object",
          "description": "Set the value of these items to the value. So `'license':MIT` would set the `license` property of the yaml file to 'MIT'",
          "additionalProperties": {
            "type": "string"
          }
        },
        "skip": {
          "type": "array",
          "description": "A list of items to not create, copy, replace, or remove in target file",
          "items": {
            "type": "string"
          }
        },
        "skipIfNotSameFileName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "mergeGit": {
      "description": "Merge file using git merge (use with varied reliability)",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "description": "Merge type",
          "enum": ["git"]
        },
        "path": {
          "type": "string",
          "description": "Path to file to merge"
        }
      }
    },
    "mergeEnv": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "path"],
      "properties": {
        "type": {
          "type": "string",
          "enum": ["env"]
        },
        "path": {
          "type": "string"
        },
        "set": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "skip": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "create": {
          "type": "array",
          "description": "List of Environment variable names to create in target project if they are not already created",
          "items": {
            "type": "string",
            "description": "The Environment variable name"
          }
        },
        "skipIfNotSameFileName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  },
  "description": "plagiarize-me.yaml configuration schema",
  "id": "https://json.schemastore.org/plagiarize-me",
  "properties": {
    "repo": {
      "type": "object",
      "description": "Git repo of where this plagiarizable project is hosted",
      "additionalProperties": false,
      "required": ["url"],
      "properties": {
        "url": {
          "type": "string",
          "description": "The git repo url of this project"
        },
        "checkout": {
          "type": "string",
          "description": "The default branch that downstream projects should checkout when plagiarizing this project",
          "default": "master"
        }
      }
    },
    "move": {
      "type": "object",
      "description": "Files to move in target project from their previous locations",
      "properties": {
        "directories": {
          "type": "array",
          "description": "Directories to move from the target repo to the target repo. Useful for refactoring project structures",
          "items": {
            "$ref": "#/definitions/moveItems"
          }
        },
        "files": {
          "type": "array",
          "description": "Files to move from the target repo to the target repo. Useful for refactoring",
          "items": {
            "$ref": "#/definitions/moveItems"
          }
        }
      }
    },
    "run": {
      "type": "array",
      "description": "Shell commands to run after plagiarize files are done being copied and updated",
      "items": {
        "type": "object",
        "required": ["command"],
        "properties": {
          "command": {
            "type": "string",
            "description": "The shell command to run"
          },
          "parallel": {
            "type": "boolean",
            "description": "Whether or not to run this command synchronously or in parallel to other commands where `parallel: true`"
          },
          "when": {
            "oneOf": [
              {
                "type": "string",
                "enum": ["always"],
                "description": "Condition type"
              },
              {
                "type": "object",
                "description": "Run this command only if configured file does not exist in target project",
                "required": ["type", "options"],
                "additionalProperties": false,
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Condition type",
                    "enum": ["if-missing"]
                  },
                  "options": {
                    "type": "object",
                    "required": ["path"],
                    "properties": {
                      "path": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              {
                "type": "object",
                "description": "Always run this command",
                "required": ["type"],
                "additionalProperties": false,
                "properties": {
                  "type": {
                    "description": "Condition type",
                    "type": "string",
                    "enum": ["always"]
                  }
                }
              }
            ]
          }
        }
      }
    },
    "replace": {
      "required": ["strings"],
      "type": "object",
      "description": "Configuration for strings, files, and file paths to replace in target file",
      "properties": {
        "strings": {
          "description": "Strings to find in target project and be replaced with plagiarized project's values",
          "type": "object",
          "additionalProperties": {
            "type": ["string", "integer", "boolean"]
          },
          "required": ["project"],
          "properties": {
            "project": {
              "type": "string"
            }
          }
        },
        "vars": {
          "description": "Variables available to be used for finding and replacing by variable name. For example `$var_name: hello` would replace string '$var_name' with 'hello' in target project",
          "type": "object",
          "additionalProperties": {
            "type": ["string", "integer", "boolean"]
          }
        },
        "files": {
          "description": "Relative path to target files that will be completely overwritten by source files in the same path",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "create": {
      "type": "object",
      "properties": {
        "files": {
          "type": "array",
          "description": "Files to copy from plagiarized project if they do not exist in the target project",
          "items": {
            "type": "string"
          }
        },
        "andClean": {
          "type": "array",
          "description": "Files to remove commented sections from. Eg code between `// plagiarize:start:always:delete` and `// plagiarize:end:always:delete`",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "merge": {
      "type": "array",
      "items": {
        "oneOf": [
          {
            "$ref": "#/definitions/mergeJson"
          },
          {
            "$ref": "#/definitions/mergeYaml"
          },
          {
            "$ref": "#/definitions/mergeGit"
          },
          {
            "$ref": "#/definitions/mergeEnv"
          }
        ]
      }
    },
    "templates": {
      "type": "array",
      "description": "Files that are used the have similarities between instances of that that. .env files for example are similar and could be templated",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["name", "replace"],
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the template"
          },
          "replace": {
            "type": "object",
            "additionalProperties": false,
            "required": ["strings"],
            "properties": {
              "strings": {
                "type": "object",
                "description": "Values to be used as variables within the target project. So `var_name: hello` in the template configuration and `var_name: world` would replace instances of 'hello' found in the source file with with 'world' found in the target file",
                "additionalProperties": {
                  "type": ["string", "boolean", "number"]
                }
              },
              "values": {
                "type": "object",
                "description": "Values to be used as variables within the target project. So `var_name: hello` would replace instances of '$var_name' with 'hello' in the target file",
                "additionalProperties": {
                  "type": ["string", "boolean", "number", "null"]
                }
              },
              "vars": {
                "type": "object",
                "description": "Values to be used as variables within the plagiarize-me.yaml file only. So `var_name: hello` would replace '$var_name' with 'hello' in plagiarize-me.yaml",
                "additionalProperties": {
                  "type": ["string", "boolean", "number", "null"]
                }
              }
            }
          },
          "merge": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/definitions/mergeJson"
                },
                {
                  "$ref": "#/definitions/mergeYaml"
                },
                {
                  "$ref": "#/definitions/mergeGit"
                },
                {
                  "$ref": "#/definitions/mergeEnv"
                }
              ]
            }
          },
          "create": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "files": {
                "type": "array",
                "items": {
                  "type": "string",
                  "description": "The path to the file to create if it does not already exist"
                }
              }
            }
          },
          "configs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "strings": {
                  "type": "object",
                  "additionalProperties": {
                    "type": ["string", "boolean", "number"]
                  }
                },
                "vars": {
                  "type": "object",
                  "additionalProperties": {
                    "type": ["string", "boolean", "number", "null"]
                  }
                }
              }
            }
          }
        }
      }
    },
    "push": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "values": {
            "type": "object",
            "description": "Values to set when iterating through each instance",
            "additionalProperties": {
              "type": "string"
            }
          },
          "instances": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["project"],
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "git": {
            "type": "object",
            "additionalProperties": false,
            "required": ["repos", "commit", "branch", "remotes"],
            "properties": {
              "repos": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": ["remote"],
                  "properties": {
                    "local": {
                      "type": "string"
                    },
                    "remote": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": ["url", "checkout", "defaultName"],
                      "properties": {
                        "url": {
                          "type": "string"
                        },
                        "checkout": {
                          "type": "string"
                        },
                        "defaultName": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              },
              "commit": {
                "type": "object",
                "additionalProperties": false,
                "required": ["message"],
                "properties": {
                  "create": {
                    "type": "boolean",
                    "default": false
                  },
                  "message": {
                    "type": "string"
                  }
                }
              },
              "branch": {
                "type": "string"
              },
              "push": {
                "type": "boolean",
                "default": false
              },
              "remotes": {
                "type": "array",
                "description": "A list of removes to push to (if `push: true`)",
                "items": {
                  "type": "string",
                  "description": "name of the remote"
                }
              },
              "hooks": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "post-push": {
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "required": ["type", "api", "remote", "targetBranch"],
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": ["create-merge-request"]
                            },
                            "api": {
                              "type": "string",
                              "enum": ["gitlab"]
                            },
                            "envVars": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "string"
                              }
                            },
                            "remote": {
                              "type": "string"
                            },
                            "targetBranch": {
                              "type": "string"
                            },
                            "removeSourceBranch": {
                              "type": "boolean",
                              "default": false
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "required": ["replace"],
  "title": "Plagiarize Me Configuration",
  "type": "object"
}