function fieldToSchema(field) {
    switch (field.type) {
        case 'text':
            return { type: 'string' };
        case 'richText':
            return { type: 'string', format: 'html' };
        case 'number':
            return { type: 'number' };
        case 'boolean':
            return { type: 'boolean' };
        case 'date':
            return { type: 'string', format: 'date-time' };
        case 'select': {
            const sel = field;
            const values = sel.options.map((o) => o.value);
            return { type: 'string', enum: values };
        }
        case 'relationship':
            return { type: 'string', description: 'Related document ID' };
        case 'media':
            return { type: 'string', description: 'Media URL' };
        case 'json':
            return { type: 'object' };
        case 'array':
            return { type: 'array' };
        case 'email':
            return { type: 'string', format: 'email' };
        case 'url':
            return { type: 'string', format: 'uri' };
        case 'color':
            return { type: 'string' };
        case 'slug':
            return { type: 'string' };
        case 'blocks':
            return { type: 'array' };
        default:
            return { type: 'string' };
    }
}
function buildCollectionSchema(fields) {
    const properties = {};
    const required = [];
    for (const [name, field] of Object.entries(fields)) {
        properties[name] = fieldToSchema(field);
        if (field.required)
            required.push(name);
    }
    const schema = { type: 'object', properties };
    if (required.length > 0)
        schema.required = required;
    return schema;
}
function pascalCase(slug) {
    return slug
        .split(/[-_]/)
        .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
        .join('');
}
function collectionPaths(slug, labels, schemaRef) {
    const tag = labels.plural;
    const listAndCreate = {
        get: {
            operationId: `list${pascalCase(slug)}`,
            tags: [tag],
            summary: `List ${labels.plural}`,
            security: [{ cookieAuth: [] }, { bearerAuth: [] }],
            parameters: [
                { name: 'page', in: 'query', schema: { type: 'integer', default: 1 } },
                { name: 'pageSize', in: 'query', schema: { type: 'integer', default: 20, maximum: 100 } },
                { name: 'search', in: 'query', schema: { type: 'string' } },
                {
                    name: 'status',
                    in: 'query',
                    schema: { type: 'string', enum: ['DRAFT', 'PUBLISHED', 'ARCHIVED', 'SCHEDULED'] },
                },
                { name: 'locale', in: 'query', schema: { type: 'string' } },
                { name: 'sort', in: 'query', schema: { type: 'string' } },
                { name: 'order', in: 'query', schema: { type: 'string', enum: ['asc', 'desc'] } },
            ],
            responses: {
                '200': {
                    description: `Paginated list of ${labels.plural}`,
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                properties: {
                                    data: {
                                        type: 'object',
                                        properties: {
                                            docs: { type: 'array', items: { $ref: schemaRef } },
                                            total: { type: 'integer' },
                                            page: { type: 'integer' },
                                            pageSize: { type: 'integer' },
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
                '401': { description: 'Unauthorized' },
            },
        },
        post: {
            operationId: `create${pascalCase(slug)}`,
            tags: [tag],
            summary: `Create a ${labels.singular}`,
            security: [{ cookieAuth: [] }, { bearerAuth: [] }],
            requestBody: {
                required: true,
                content: { 'application/json': { schema: { $ref: schemaRef } } },
            },
            responses: {
                '201': {
                    description: `${labels.singular} created`,
                    content: {
                        'application/json': {
                            schema: { type: 'object', properties: { data: { $ref: schemaRef } } },
                        },
                    },
                },
                '401': { description: 'Unauthorized' },
                '403': { description: 'Insufficient permissions' },
            },
        },
    };
    const singleItem = {
        get: {
            operationId: `get${pascalCase(slug)}`,
            tags: [tag],
            summary: `Get a ${labels.singular} by ID`,
            security: [{ cookieAuth: [] }, { bearerAuth: [] }],
            parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
            responses: {
                '200': {
                    description: `${labels.singular} details`,
                    content: {
                        'application/json': {
                            schema: { type: 'object', properties: { data: { $ref: schemaRef } } },
                        },
                    },
                },
                '401': { description: 'Unauthorized' },
                '404': { description: 'Not found' },
            },
        },
        put: {
            operationId: `update${pascalCase(slug)}`,
            tags: [tag],
            summary: `Update a ${labels.singular}`,
            security: [{ cookieAuth: [] }, { bearerAuth: [] }],
            parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
            requestBody: {
                required: true,
                content: { 'application/json': { schema: { $ref: schemaRef } } },
            },
            responses: {
                '200': {
                    description: `${labels.singular} updated`,
                    content: {
                        'application/json': {
                            schema: { type: 'object', properties: { data: { $ref: schemaRef } } },
                        },
                    },
                },
                '401': { description: 'Unauthorized' },
                '403': { description: 'Insufficient permissions' },
                '404': { description: 'Not found' },
            },
        },
        delete: {
            operationId: `delete${pascalCase(slug)}`,
            tags: [tag],
            summary: `Delete a ${labels.singular}`,
            security: [{ cookieAuth: [] }, { bearerAuth: [] }],
            parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
            responses: {
                '200': {
                    description: `${labels.singular} deleted`,
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                properties: {
                                    data: { type: 'object', properties: { success: { type: 'boolean' } } },
                                },
                            },
                        },
                    },
                },
                '401': { description: 'Unauthorized' },
                '403': { description: 'Insufficient permissions' },
                '404': { description: 'Not found' },
            },
        },
    };
    return {
        [`/collections/${slug}`]: listAndCreate,
        [`/collections/${slug}/{id}`]: singleItem,
    };
}
function staticPaths() {
    return {
        '/auth/login': {
            post: {
                operationId: 'login',
                tags: ['Auth'],
                summary: 'Authenticate with email and password',
                requestBody: {
                    required: true,
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                required: ['email', 'password'],
                                properties: {
                                    email: { type: 'string', format: 'email' },
                                    password: { type: 'string' },
                                },
                            },
                        },
                    },
                },
                responses: {
                    '200': { description: 'Login successful' },
                    '401': { description: 'Invalid credentials' },
                    '429': { description: 'Rate limited' },
                },
            },
        },
        '/auth/logout': {
            post: {
                operationId: 'logout',
                tags: ['Auth'],
                summary: 'End the current session',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                responses: {
                    '200': { description: 'Logged out' },
                    '401': { description: 'Unauthorized' },
                },
            },
        },
        '/auth/csrf': {
            get: {
                operationId: 'getCsrfToken',
                tags: ['Auth'],
                summary: 'Get a CSRF token',
                responses: {
                    '200': {
                        description: 'CSRF token',
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'object',
                                    properties: {
                                        data: { type: 'object', properties: { token: { type: 'string' } } },
                                    },
                                },
                            },
                        },
                    },
                },
            },
        },
        '/public/globals/{slug}': {
            get: {
                operationId: 'getPublicGlobal',
                tags: ['Public'],
                summary: 'Read a public global document',
                description: "Returns global data without requiring an authenticated session. Honours the global's `access.read` policy when set; defaults to public when no policy is configured. Used by createSiteClient.getGlobal() and createServerSiteClient(prisma, config).getGlobal().",
                parameters: [{ name: 'slug', in: 'path', required: true, schema: { type: 'string' } }],
                responses: {
                    '200': {
                        description: 'Global data',
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'object',
                                    properties: { data: { type: 'object', additionalProperties: true } },
                                },
                            },
                        },
                    },
                    '403': { description: 'Forbidden by access.read' },
                    '404': { description: 'Global not declared or no document exists' },
                },
            },
        },
        '/resolve': {
            get: {
                operationId: 'resolveDocument',
                tags: ['Public'],
                summary: 'Resolve a public URL path to a published document',
                description: 'Maps a path (e.g. `/blog/hello-world`) to the matching PUBLISHED document by walking collection url-prefixes, then by slug. Returns the document data plus any layout variants. Internal `_layout` is lifted to the top-level `layout` field. Powers createSiteClient().resolveDocument().',
                parameters: [
                    {
                        name: 'path',
                        in: 'query',
                        required: true,
                        schema: { type: 'string' },
                        description: 'URL path with leading slash, e.g. "/about" or "/"',
                    },
                ],
                responses: {
                    '200': {
                        description: 'Resolved document',
                        content: {
                            'application/json': {
                                schema: {
                                    type: 'object',
                                    properties: {
                                        data: {
                                            type: 'object',
                                            properties: {
                                                id: { type: 'string' },
                                                collection: { type: 'string' },
                                                status: { type: 'string' },
                                                publishedAt: { type: 'string', format: 'date-time', nullable: true },
                                                data: { type: 'object', additionalProperties: true },
                                                structuredData: { type: 'object', nullable: true },
                                            },
                                        },
                                        layout: { type: 'object', additionalProperties: true },
                                    },
                                },
                            },
                        },
                    },
                    '400': { description: 'Missing required `path` parameter' },
                    '404': { description: 'No published document at the given path' },
                },
            },
        },
        '/media': {
            get: {
                operationId: 'listMedia',
                tags: ['Media'],
                summary: 'List uploaded media files',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                parameters: [
                    { name: 'page', in: 'query', schema: { type: 'integer', default: 1 } },
                    { name: 'pageSize', in: 'query', schema: { type: 'integer', default: 20 } },
                    { name: 'folderId', in: 'query', schema: { type: 'string' } },
                ],
                responses: {
                    '200': { description: 'Paginated media list' },
                    '401': { description: 'Unauthorized' },
                },
            },
        },
        '/media/upload': {
            post: {
                operationId: 'uploadMedia',
                tags: ['Media'],
                summary: 'Upload a media file',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                requestBody: {
                    required: true,
                    content: {
                        'multipart/form-data': {
                            schema: {
                                type: 'object',
                                properties: {
                                    file: { type: 'string', format: 'binary' },
                                    skipOptimize: { type: 'string', enum: ['true', 'false'] },
                                },
                                required: ['file'],
                            },
                        },
                    },
                },
                responses: {
                    '201': { description: 'Media uploaded' },
                    '401': { description: 'Unauthorized' },
                    '413': { description: 'File too large' },
                },
            },
        },
        '/search': {
            get: {
                operationId: 'search',
                tags: ['Search'],
                summary: 'Full-text search across documents',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                parameters: [
                    { name: 'q', in: 'query', required: true, schema: { type: 'string' } },
                    { name: 'collection', in: 'query', schema: { type: 'string' } },
                    { name: 'page', in: 'query', schema: { type: 'integer', default: 1 } },
                    { name: 'pageSize', in: 'query', schema: { type: 'integer', default: 20 } },
                ],
                responses: {
                    '200': { description: 'Search results' },
                    '401': { description: 'Unauthorized' },
                },
            },
        },
        '/webhooks': {
            get: {
                operationId: 'listWebhooks',
                tags: ['Webhooks'],
                summary: 'List configured webhook endpoints',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                responses: {
                    '200': { description: 'List of webhook endpoints' },
                    '401': { description: 'Unauthorized' },
                    '403': { description: 'Admin access required' },
                },
            },
            post: {
                operationId: 'createWebhook',
                tags: ['Webhooks'],
                summary: 'Register a new webhook endpoint',
                security: [{ cookieAuth: [] }, { bearerAuth: [] }],
                requestBody: {
                    required: true,
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                required: ['url', 'events'],
                                properties: {
                                    url: { type: 'string', format: 'uri' },
                                    events: { type: 'array', items: { type: 'string' } },
                                    name: { type: 'string' },
                                    secret: { type: 'string' },
                                    active: { type: 'boolean', default: true },
                                },
                            },
                        },
                    },
                },
                responses: {
                    '201': { description: 'Webhook created' },
                    '401': { description: 'Unauthorized' },
                    '403': { description: 'Admin access required' },
                },
            },
        },
        '/forms/{id}/submit': {
            post: {
                operationId: 'submitForm',
                tags: ['Forms'],
                summary: 'Submit a public form',
                parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'string' } }],
                requestBody: {
                    required: true,
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                required: ['fields'],
                                properties: {
                                    fields: { type: 'object', additionalProperties: true },
                                    attribution: { type: 'object', additionalProperties: true },
                                },
                            },
                        },
                    },
                },
                responses: {
                    '201': { description: 'Form submitted' },
                    '404': { description: 'Form not found' },
                    '429': { description: 'Rate limited' },
                },
            },
        },
    };
}
export function generateOpenAPISpec(config) {
    const schemas = {};
    const paths = {};
    for (const [slug, collection] of Object.entries(config.collections)) {
        const schemaName = pascalCase(slug);
        schemas[schemaName] = buildCollectionSchema(collection.fields);
        const generated = collectionPaths(slug, collection.labels, `#/components/schemas/${schemaName}`);
        Object.assign(paths, generated);
    }
    Object.assign(paths, staticPaths());
    return {
        openapi: '3.1.0',
        info: {
            title: 'Actuate CMS API',
            version: '1.0.0',
            description: 'Auto-generated API specification for this Actuate CMS instance.',
        },
        servers: [{ url: '/api/cms' }],
        security: [{ cookieAuth: [] }, { bearerAuth: [] }],
        paths,
        components: {
            securitySchemes: {
                cookieAuth: {
                    type: 'apiKey',
                    in: 'cookie',
                    name: 'actuate_session',
                },
                bearerAuth: {
                    type: 'http',
                    scheme: 'bearer',
                    bearerFormat: 'JWT',
                },
            },
            schemas,
        },
    };
}
//# sourceMappingURL=openapi.js.map