{
	"$schema": "http://json-schema.org/draft-07/schema#",
	"$id": "https://lazypock.gnuzd.dev/backup.schema.json",
	"title": "LazyPock backup / import payload",
	"description": "Full-database backup format accepted by POST /api/import and the Studio (Settings → Import / Backups). Generate this shape with GET /api/export. Documented at https://lazypock.gnuzd.dev/backup",
	"$comment": "The importer also accepts a bare array of collection objects, and PocketBase 23+ collections that use a top-level \"fields\" key with flat type options (see the docs page). This schema describes the canonical LazyPock export envelope.",
	"type": "object",
	"required": ["collections"],
	"properties": {
		"collections": {
			"type": "array",
			"description": "Every collection to create/update, with its records.",
			"items": { "$ref": "#/definitions/collection" }
		}
	},
	"definitions": {
		"collection": {
			"type": "object",
			"required": ["name", "type"],
			"if": { "properties": { "type": { "const": "view" } }, "required": ["type"] },
			"then": {},
			"else": { "anyOf": [{ "required": ["schema"] }, { "required": ["fields"] }] },
			"properties": {
				"id": {
					"type": "string",
					"description": "Existing collection id. Omit it and the collection is matched by name."
				},
				"name": {
					"type": "string",
					"pattern": "^[a-z][a-z0-9_]*$",
					"description": "Table name: starts with a letter, lowercase letters/numbers/underscores only."
				},
				"type": {
					"enum": ["base", "auth", "view"],
					"description": "base = plain records; auth = accounts with email + write-only password; view = a read-only collection over a SQL query."
				},
				"schema": {
					"type": "array",
					"description": "Field definitions. PocketBase exports call this \"fields\" instead — send either, and if both are present \"fields\" wins.",
					"items": { "$ref": "#/definitions/field" }
				},
				"fields": {
					"type": "array",
					"description": "PocketBase 23+ alias for \"schema\".",
					"items": { "$ref": "#/definitions/field" }
				},
				"rules": {
					"$ref": "#/definitions/rules"
				},
				"options": {
					"type": "object",
					"description": "Collection-level options: indexes for a table, or the query for a view.",
					"properties": {
						"indexes": {
							"type": "array",
							"description": "Custom indexes, as expressions (\"UNIQUE email\", \"created_at DESC, id\") or a full PocketBase `CREATE INDEX ...` statement. Only the collection's own columns, and only plain columns (no expressions). Not for a view collection.",
							"items": { "type": "string" }
						},
						"view_query": { "type": "string" },
						"view_builder": { "type": "object" }
					},
					"additionalProperties": true
				},
				"hooks": {
					"type": "object",
					"description": "Collection hook configuration. Usually {}."
				},
				"viewQuery": {
					"type": "string",
					"description": "PocketBase's spelling of a view's SQL; folded into options.view_query."
				},
				"viewBuilder": {
					"type": "object",
					"description": "The no-code view spec; rendered to SQL and stored as options.view_query."
				},
				"records": {
					"type": "array",
					"description": "Records to upsert by id. A view carries none: its rows are its query's.",
					"items": { "type": "object" }
				}
			},
			"additionalProperties": true
		},
		"field": {
			"type": "object",
			"required": ["name", "type"],
			"properties": {
				"name": {
					"type": "string",
					"pattern": "^[A-Za-z][A-Za-z0-9_]*$",
					"description": "Field name. Kept verbatim (case preserved); it is also the API key and DB column name."
				},
				"type": {
					"enum": [
						"text",
						"editor",
						"number",
						"bool",
						"email",
						"url",
						"date",
						"datetime",
						"autodate",
						"select",
						"multi_select",
						"file",
						"multi_file",
						"relation",
						"json",
						"geo",
						"password"
					]
				},
				"required": { "type": "boolean", "default": false },
				"unique": { "type": "boolean", "default": false },
				"indexed": { "type": "boolean", "default": false },
				"hidden": {
					"type": "boolean",
					"default": false,
					"description": "Never returned in API responses / not shown in the Studio."
				},
				"system": {
					"type": "boolean",
					"default": false,
					"description": "System-managed field. Fields with system=true are stripped on import (e.g. PocketBase's own \"id\" field) — do not include them."
				},
				"default": {
					"description": "Default value applied when the field is omitted on write."
				},
				"options": {
					"type": "object",
					"description": "Type-specific settings, e.g. { \"maxSelect\": 3 } for a multi select, { \"values\": [...] } for select, { \"collection\": \"other\" } for relation, { \"onCreate\": true } for autodate.",
					"additionalProperties": true
				},
				"sort_order": { "type": "integer", "description": "Display/column order." }
			},
			"additionalProperties": true
		},
		"rules": {
			"type": "object",
			"description": "PocketBase filter rules. null = superusers only; \"\" = public.",
			"properties": {
				"listRule": { "$ref": "#/definitions/nullableString" },
				"viewRule": { "$ref": "#/definitions/nullableString" },
				"createRule": { "$ref": "#/definitions/nullableString" },
				"updateRule": { "$ref": "#/definitions/nullableString" },
				"deleteRule": { "$ref": "#/definitions/nullableString" },
				"manageRule": { "$ref": "#/definitions/nullableString" }
			},
			"additionalProperties": true
		},
		"nullableString": {
			"type": ["string", "null"]
		}
	}
}
