export const EMPTY_OBJECT_SCHEMA = { type: 'object', properties: {}, additionalProperties: false };
export const STRING_SCHEMA = { type: 'string' };
export const BOOLEAN_SCHEMA = { type: 'boolean' };
export const NUMBER_SCHEMA = { type: 'number' };
const NULL_SCHEMA = { type: 'null' };
export const JSON_VALUE_SCHEMA = {};
export const JSON_OBJECT_SCHEMA = {
    type: 'object',
    additionalProperties: JSON_VALUE_SCHEMA,
};
export const JSON_ARRAY_SCHEMA = {
    type: 'array',
    items: JSON_VALUE_SCHEMA,
};
Object.assign(JSON_VALUE_SCHEMA, {
    anyOf: [
        STRING_SCHEMA,
        NUMBER_SCHEMA,
        BOOLEAN_SCHEMA,
        NULL_SCHEMA,
        JSON_OBJECT_SCHEMA,
        JSON_ARRAY_SCHEMA,
    ],
});
export function arraySchema(itemSchema) {
    return { type: 'array', items: itemSchema };
}
export function objectSchema(properties, required = [], options = {}) {
    return {
        type: 'object',
        properties,
        ...(required.length > 0 ? { required: [...required] } : {}),
        additionalProperties: options.additionalProperties ?? false,
    };
}
export const GATEWAY_HTTP_BINDING_SCHEMA = objectSchema({
    method: STRING_SCHEMA,
    path: STRING_SCHEMA,
}, ['method', 'path']);
export const METHOD_DESCRIPTOR_SCHEMA = objectSchema({
    id: STRING_SCHEMA,
    title: STRING_SCHEMA,
    description: STRING_SCHEMA,
    category: STRING_SCHEMA,
    source: STRING_SCHEMA,
    access: STRING_SCHEMA,
    transport: arraySchema(STRING_SCHEMA),
    scopes: arraySchema(STRING_SCHEMA),
    http: GATEWAY_HTTP_BINDING_SCHEMA,
    events: arraySchema(STRING_SCHEMA),
    inputSchema: JSON_OBJECT_SCHEMA,
    outputSchema: JSON_OBJECT_SCHEMA,
    pluginId: STRING_SCHEMA,
    dangerous: BOOLEAN_SCHEMA,
    invokable: BOOLEAN_SCHEMA,
    metadata: JSON_OBJECT_SCHEMA,
}, ['id', 'title', 'description', 'category', 'source', 'access', 'transport', 'scopes']);
export const EVENT_DESCRIPTOR_SCHEMA = objectSchema({
    id: STRING_SCHEMA,
    title: STRING_SCHEMA,
    description: STRING_SCHEMA,
    category: STRING_SCHEMA,
    source: STRING_SCHEMA,
    transport: arraySchema(STRING_SCHEMA),
    scopes: arraySchema(STRING_SCHEMA),
    domains: arraySchema(STRING_SCHEMA),
    wireEvents: arraySchema(STRING_SCHEMA),
    outputSchema: JSON_OBJECT_SCHEMA,
    pluginId: STRING_SCHEMA,
    metadata: JSON_OBJECT_SCHEMA,
}, ['id', 'title', 'description', 'category', 'source', 'transport', 'scopes']);
export function listOutputSchema(key, itemSchema) {
    return objectSchema({ [key]: arraySchema(itemSchema) }, [key], { additionalProperties: false });
}
export function entityOutputSchema(key, entitySchema) {
    return objectSchema({ [key]: entitySchema }, [key], { additionalProperties: false });
}
export function actionResultOutputSchema(key, entitySchema) {
    return objectSchema({
        [key]: entitySchema,
    }, [key], { additionalProperties: true });
}
export function bodyEnvelopeSchema(properties = {}, required = []) {
    return objectSchema({
        ...properties,
    }, required, { additionalProperties: true });
}
export function methodDescriptor(input) {
    return {
        source: input.source ?? 'builtin',
        transport: input.transport ?? ['http', 'ws'],
        access: input.access ?? 'authenticated',
        ...input,
    };
}
export function eventDescriptor(input) {
    return {
        source: input.source ?? 'builtin',
        ...input,
    };
}
export function runtimeEventId(domain) {
    return `runtime.${domain}`;
}
export function runtimeDomainEvent(domain, description) {
    return eventDescriptor({
        id: runtimeEventId(domain),
        title: `${domain} Domain Events`,
        description,
        category: 'runtime-domain',
        transport: ['sse', 'ws'],
        scopes: ['read:events'],
        domains: [domain],
        wireEvents: [domain],
        outputSchema: JSON_OBJECT_SCHEMA,
    });
}
