"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.APP_SDK_VIZ_CONTEXT_REQUEST_MESSAGE = exports.APP_SDK_DATA_APP_VIZ_CONTEXT_MESSAGE = exports.getEffectiveOptionValues = exports.dataAppVizJsonSchema = exports.dataAppVizSchema = exports.formatPromptWithClarifications = exports.DEFAULT_DATA_APP_CLAUDE_MODEL = exports.DATA_APP_CLAUDE_MODELS = exports.DATA_APP_TEMPLATES = exports.DATA_APP_VIZ_TEMPLATE = exports.getAppDisplayName = exports.isAppVersionInProgress = exports.APP_VERSION_CANCELLED_BY_USER = exports.APP_VERSION_TERMINAL_STATUSES = exports.APP_VERSION_STAGE_ORDER = void 0;
const zod_1 = require("zod");
const zod_to_json_schema_1 = require("zod-to-json-schema");
/**
 * Ordered pipeline stages. Index position determines progression — used to
 * skip completed stages when a build is retried after a worker crash.
 * 'ready' is included as the final stage; 'error' is terminal but not a
 * stage (not reachable through normal progression).
 */
exports.APP_VERSION_STAGE_ORDER = [
    'pending',
    'sandbox',
    'catalog',
    'generating',
    'building',
    'packaging',
    'ready',
];
exports.APP_VERSION_TERMINAL_STATUSES = ['ready', 'error'];
/**
 * Error message stamped on a version when the user cancels its build. There is
 * no dedicated 'cancelled' status — cancellation is an 'error' carrying this
 * marker, which the pipeline also reads to detect that a previous prompt was
 * cancelled mid-generation.
 */
exports.APP_VERSION_CANCELLED_BY_USER = 'Cancelled by user';
const isAppVersionInProgress = (status) => !exports.APP_VERSION_TERMINAL_STATUSES.includes(status);
exports.isAppVersionInProgress = isAppVersionInProgress;
/**
 * Data apps are created with an empty name and only get an auto-generated
 * title after their first version builds successfully. If that build never
 * completes the name stays blank. Everywhere an app name is shown to the user,
 * fall back to a stable, identifiable placeholder instead of rendering nothing
 * — the uuid suffix keeps two unnamed apps distinguishable. Use this as the
 * single source of truth so the convention stays consistent across the UI.
 */
const getAppDisplayName = (name, appUuid) => name.trim().length > 0 ? name : `Untitled app ${appUuid.slice(0, 8)}`;
exports.getAppDisplayName = getAppDisplayName;
/** Starter template for a single-tile renderer that emits a typed viz schema. */
exports.DATA_APP_VIZ_TEMPLATE = 'data_app_viz';
exports.DATA_APP_TEMPLATES = [
    'dashboard',
    'slideshow',
    'pdf',
    'custom',
    exports.DATA_APP_VIZ_TEMPLATE,
];
/**
 * Claude model used to generate / iterate the data app inside the sandbox.
 * Mapped to the Claude CLI's `--model <alias>` flag verbatim. Persisted
 * per-version on `AppVersionResources.claudeModel` so the user can switch
 * mid-iteration without losing the record of which model built which version.
 */
exports.DATA_APP_CLAUDE_MODELS = ['opus', 'sonnet', 'haiku'];
exports.DEFAULT_DATA_APP_CLAUDE_MODEL = 'sonnet';
/**
 * Fold clarifications into the prompt sent to the sandbox. The persisted
 * prompt stays as the user's original words — clarifications travel
 * separately on `resources.clarifications` for chat rendering.
 */
const formatPromptWithClarifications = (prompt, clarifications) => {
    if (!clarifications || clarifications.length === 0)
        return prompt;
    const qa = clarifications
        .map((c, i) => `${i + 1}. Q: ${c.question.trim()}\n   A: ${c.answer.trim()}`)
        .join('\n');
    return `${prompt}\n\nClarifications:\n${qa}`;
};
exports.formatPromptWithClarifications = formatPromptWithClarifications;
const uniqueNames = (arr) => new Set(arr.map((a) => a.name)).size === arr.length;
const optionBase = {
    name: zod_1.z.string().min(1),
    label: zod_1.z.string(),
    group: zod_1.z.string().optional(),
};
// Runtime validator for the untrusted generated declaration. Also the source
// for the JSON Schema embedded in the generation prompt.
exports.dataAppVizSchema = zod_1.z.object({
    fields: zod_1.z
        .array(zod_1.z.object({
        name: zod_1.z.string().min(1),
        label: zod_1.z.string(),
        type: zod_1.z.enum(['dimension', 'metric', 'series']),
        required: zod_1.z.boolean(),
    }))
        .refine(uniqueNames, 'duplicate field name'),
    configOptions: zod_1.z
        .array(zod_1.z.discriminatedUnion('type', [
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('boolean'),
            default: zod_1.z.boolean(),
        }),
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('select'),
            choices: zod_1.z
                .array(zod_1.z.object({ value: zod_1.z.string(), label: zod_1.z.string() }))
                .min(1),
            default: zod_1.z.string(),
        }),
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('number'),
            default: zod_1.z.number(),
            min: zod_1.z.number().optional(),
            max: zod_1.z.number().optional(),
        }),
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('text'),
            default: zod_1.z.string(),
        }),
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('color'),
            default: zod_1.z.string(),
        }),
        zod_1.z.object({
            ...optionBase,
            type: zod_1.z.literal('palette'),
            default: zod_1.z.array(zod_1.z.string()),
        }),
    ]))
        .default([])
        .refine(uniqueNames, 'duplicate option name'),
});
const dataAppVizSchemaMatchesApiType = true;
void dataAppVizSchemaMatchesApiType;
// JSON Schema form of `dataAppVizSchema` for the generator CLI's `--json-schema`
// flag. Refinements (e.g. unique names) don't survive the conversion and stay
// enforced by the runtime `safeParse`.
exports.dataAppVizJsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(exports.dataAppVizSchema);
/** Effective option values = stored value ?? declared default (derive, never seed). */
const getEffectiveOptionValues = (configOptions, optionValues) => Object.fromEntries(configOptions.map((o) => [o.name, optionValues[o.name] ?? o.default]));
exports.getEffectiveOptionValues = getEffectiveOptionValues;
// postMessage type the host uses to push render context into the sandboxed
// iframe over the existing app SDK bridge (no new transport).
exports.APP_SDK_DATA_APP_VIZ_CONTEXT_MESSAGE = 'lightdash:sdk:data-app-viz-context';
// postMessage type the iframe posts on mount (via the SDK's useVizContext) to
// ask the host to push the current context — the renderer may mount after the
// host's first push, so this handshake replaces blind timed re-sends.
exports.APP_SDK_VIZ_CONTEXT_REQUEST_MESSAGE = 'lightdash:sdk:viz-context-request';
//# sourceMappingURL=types.js.map