"use strict";
/**
 * Shared destination derivation for generated ("fresh" / zero-to-one) projects.
 *
 * Both kickoff paths — `start_variants(mode='zero_to_one')` and the
 * source-grounded `create_zero_to_one_project` — turn a prompt into the same
 * thing: a slugified subproject directory under `<workspaceRoot>/.rivet/<slug>/`.
 * They used to derive it with two near-identical copies of the same logic,
 * which had already drifted: the `start_variants` path skipped
 * `normalizeWorkspaceRoot`, so a `destinationParent` that already sat inside a
 * `.rivet/` tree produced a nested `.rivet/<slug>/.rivet/<slug2>` that breaks
 * preview/history path resolution. Centralizing here removes the duplication
 * and gives both paths the nesting guard.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizeWorkspaceRoot = exports.slugifyPrompt = void 0;
exports.deriveGeneratedDestination = deriveGeneratedDestination;
const crypto_1 = require("crypto");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const viteReactTs_1 = require("../../services/templates/viteReactTs");
const SLUG_SUFFIX_BYTES = 2;
/**
 * Slugify a prompt into a directory-safe kebab-case name with a short random
 * suffix so concurrent calls with the same prompt don't collide.
 */
const slugifyPrompt = (prompt) => {
    const base = prompt
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 40);
    const suffix = (0, crypto_1.randomBytes)(SLUG_SUFFIX_BYTES).toString('hex');
    return base ? `${base}-${suffix}` : `rivet-app-${suffix}`;
};
exports.slugifyPrompt = slugifyPrompt;
/**
 * Collapse a candidate workspace root back to the real workspace when it points
 * inside a `.rivet/` tree.
 *
 * The editor bridge can become bound to a previously generated subproject
 * (`<root>/.rivet/<slug>`) — e.g. after the user opens that subproject in the
 * visual editor. Without this guard the next zero-to-one session would resolve
 * its `destinationParent` to that subproject and join `.rivet/<slug>` onto it,
 * producing a nested `<root>/.rivet/<slug>/.rivet/<slug2>`. That nesting breaks
 * preview/history path resolution (everything is rooted at `workspaceRoot`), so
 * generated variants land on disk but render blank on click.
 *
 * Truncating at the segment before the first `.rivet` keeps the single-`.rivet`
 * invariant. Idempotent: a path with no `.rivet` segment is returned unchanged.
 */
const normalizeWorkspaceRoot = (candidate) => {
    const resolved = path_1.default.resolve(candidate);
    const segments = resolved.split(path_1.default.sep);
    const idx = segments.indexOf('.rivet');
    if (idx <= 0)
        return resolved;
    return segments.slice(0, idx).join(path_1.default.sep) || path_1.default.sep;
};
exports.normalizeWorkspaceRoot = normalizeWorkspaceRoot;
/**
 * Resolve the destination for a generated project from a prompt.
 *
 * Destination-parent default chain: explicit `destinationParent` arg →
 * currently-open editor project → MCP server cwd. cwd (not homedir) so
 * generated projects land near where the user is actually working rather than
 * dumped at the home root.
 *
 * Returns a discriminated result so each caller can format the failure in its
 * own response shape. On `ok`, the parent of `destinationPath` has been
 * created so the materialize step at commit time has a directory to write into.
 */
function deriveGeneratedDestination(args) {
    const destinationParent = args.destinationParent ?? args.editorProjectPath ?? args.cwd();
    if (!path_1.default.isAbsolute(destinationParent)) {
        return {
            ok: false,
            errorCode: 'SCHEMA_VALIDATION_FAILED',
            message: `destinationParent must be absolute; got '${destinationParent}'.`,
        };
    }
    const slug = (0, exports.slugifyPrompt)(args.prompt);
    // Subprojects nest under `<workspaceRoot>/.rivet/<slug>/` so every Rivet
    // artifact (generated app files, variant history, manifests) lives in one
    // hidden directory — the user's working dir stays clean. Normalize first so
    // we never nest one `.rivet/` inside another.
    const workspaceRoot = (0, exports.normalizeWorkspaceRoot)(destinationParent);
    const destinationPath = path_1.default.join(workspaceRoot, '.rivet', slug);
    const isEmpty = args.destinationIsEmpty ?? viteReactTs_1.isDestinationEmpty;
    if (!isEmpty(destinationPath)) {
        return {
            ok: false,
            errorCode: 'DESTINATION_NOT_EMPTY',
            message: `Destination '${destinationPath}' is not empty.`,
        };
    }
    const mkdir = args.mkdir ?? ((dir) => fs_1.default.mkdirSync(dir, { recursive: true }));
    mkdir(path_1.default.dirname(destinationPath));
    return { ok: true, slug, workspaceRoot, destinationPath };
}
//# sourceMappingURL=generatedDestination.js.map