"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVendureApp = createVendureApp;
const prompts_1 = require("@clack/prompts");
const shared_constants_1 = require("@vendure/common/lib/shared-constants");
const commander_1 = require("commander");
const crypto_1 = require("crypto");
const fs_extra_1 = __importDefault(require("fs-extra"));
const handlebars_1 = __importDefault(require("handlebars"));
const node_child_process_1 = require("node:child_process");
const promises_1 = require("node:timers/promises");
const open_1 = __importDefault(require("open"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const picocolors_1 = __importDefault(require("picocolors"));
const constants_1 = require("./constants");
const gather_user_responses_1 = require("./gather-user-responses");
const helpers_1 = require("./helpers");
const logger_1 = require("./logger");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageJson = require('../package.json');
(0, helpers_1.checkNodeVersion)(constants_1.REQUIRED_NODE_VERSION);
let projectName;
// Set the environment variable which can then be used to
// conditionally modify behaviour of core or plugins.
const createEnvVar = 'CREATING_VENDURE_APP';
process.env[createEnvVar] = 'true';
commander_1.program
    .version(packageJson.version)
    .arguments('<project-directory>')
    .usage(`${picocolors_1.default.green('<project-directory>')} [options]`)
    .action(name => {
    projectName = name;
})
    .option('--log-level <logLevel>', "Log level, either 'silent', 'info', or 'verbose'", /^(silent|info|verbose)$/i, 'info')
    .option('--verbose', 'Alias for --log-level verbose', false)
    .option('--use-npm', 'Uses npm rather than as the default package manager. DEPRECATED: Npm is now the default')
    .option('--ci', 'Runs without prompts for use in CI scenarios', false)
    .option('--with-storefront', 'Include Next.js storefront (only used with --ci)', false)
    .parse(process.argv);
const options = commander_1.program.opts();
void createVendureApp(projectName, options.useNpm, options.verbose ? 'verbose' : options.logLevel || 'info', options.ci, options.withStorefront).catch(err => {
    (0, logger_1.log)(err);
    process.exit(1);
});
async function createVendureApp(name, _useNpm, // Deprecated: npm is now the default package manager
logLevel, isCi = false, withStorefront = false) {
    var _a, _b, _c;
    (0, logger_1.setLogLevel)(logLevel);
    if (!runPreChecks(name)) {
        return;
    }
    (0, prompts_1.intro)(`Let's create a ${picocolors_1.default.blue(picocolors_1.default.bold('Vendure App'))} ✨ ${picocolors_1.default.dim(`v${packageJson.version}`)}`);
    const mode = isCi
        ? 'ci'
        : (await (0, prompts_1.select)({
            message: 'How should we proceed?',
            options: [
                { label: 'Quick Start', value: 'quick', hint: 'Get up an running in a single step' },
                {
                    label: 'Manual Configuration',
                    value: 'manual',
                    hint: 'Customize your Vendure project with more advanced settings',
                },
            ],
            initialValue: 'quick',
        }));
    (0, helpers_1.checkCancel)(mode);
    const portSpinner = (0, prompts_1.spinner)();
    let port;
    let storefrontPort = constants_1.STOREFRONT_PORT;
    portSpinner.start(`Establishing port...`);
    try {
        port = await (0, helpers_1.findAvailablePort)(constants_1.SERVER_PORT, constants_1.PORT_SCAN_RANGE);
        portSpinner.stop(`Using port ${port}`);
    }
    catch (e) {
        portSpinner.stop(picocolors_1.default.red('Could not find an available port'));
        (0, prompts_1.outro)(e.message);
        process.exit(1);
    }
    process.env.PORT = port.toString();
    const root = path_1.default.resolve(name);
    const appName = path_1.default.basename(root);
    const scaffoldExists = (0, helpers_1.scaffoldAlreadyExists)(root, name);
    const packageManager = 'npm';
    if (scaffoldExists) {
        (0, logger_1.log)(picocolors_1.default.yellow('It appears that a new Vendure project scaffold already exists. Re-using the existing files...'), { newline: 'after' });
    }
    const { dbType, configSource, envSource, envDtsSource, indexSource, indexWorkerSource, readmeSource, dockerfileSource, dockerComposeSource, tsconfigDashboardSource, viteConfigSource, populateProducts, includeStorefront, } = mode === 'ci'
        ? await (0, gather_user_responses_1.getCiConfiguration)(root, packageManager, port, withStorefront)
        : mode === 'manual'
            ? await (0, gather_user_responses_1.getManualConfiguration)(root, packageManager, port)
            : await (0, gather_user_responses_1.getQuickStartConfiguration)(root, packageManager, port);
    // Determine the server root directory (either root or apps/server for monorepo)
    const serverRoot = includeStorefront ? path_1.default.join(root, 'apps', 'server') : root;
    const storefrontRoot = path_1.default.join(root, 'apps', 'storefront');
    // Find an available storefront port if including storefront
    if (includeStorefront) {
        const storefrontPortSpinner = (0, prompts_1.spinner)();
        storefrontPortSpinner.start(`Establishing storefront port...`);
        try {
            // Start scanning from the higher of STOREFRONT_PORT or serverPort + 1
            // to avoid conflicts with the server port
            const storefrontStartPort = Math.max(constants_1.STOREFRONT_PORT, port + 1);
            storefrontPort = await (0, helpers_1.findAvailablePort)(storefrontStartPort, constants_1.PORT_SCAN_RANGE);
            storefrontPortSpinner.stop(`Using storefront port ${storefrontPort}`);
        }
        catch (e) {
            storefrontPortSpinner.stop(picocolors_1.default.red('Could not find an available storefront port'));
            (0, prompts_1.outro)(e.message);
            process.exit(1);
        }
    }
    process.chdir(root);
    if (packageManager !== 'npm' && !(0, helpers_1.checkThatNpmCanReadCwd)()) {
        process.exit(1);
    }
    const setupSpinner = (0, prompts_1.spinner)();
    const projectType = includeStorefront ? 'monorepo' : 'project';
    setupSpinner.start(`Setting up your new Vendure ${projectType} in ${picocolors_1.default.green(root)}\nThis may take a few minutes...`);
    const assetPath = (fileName) => path_1.default.join(__dirname, '../assets', fileName);
    const templatePath = (fileName) => path_1.default.join(__dirname, '../assets/monorepo', fileName);
    if (includeStorefront) {
        // Create monorepo structure
        await fs_extra_1.default.ensureDir(path_1.default.join(root, 'apps'));
        await fs_extra_1.default.ensureDir(serverRoot);
        await fs_extra_1.default.ensureDir(path_1.default.join(serverRoot, 'src'));
        // Generate root package.json from template
        const rootPackageTemplate = await fs_extra_1.default.readFile(templatePath('root-package.json.hbs'), 'utf-8');
        const rootPackageContent = handlebars_1.default.compile(rootPackageTemplate)({ name: appName });
        fs_extra_1.default.writeFileSync(path_1.default.join(root, 'package.json'), rootPackageContent + os_1.default.EOL);
        // Generate root README from template
        const rootReadmeTemplate = await fs_extra_1.default.readFile(templatePath('root-readme.hbs'), 'utf-8');
        const rootReadmeContent = handlebars_1.default.compile(rootReadmeTemplate)({
            name: appName,
            serverPort: port,
            storefrontPort,
            superadminIdentifier: shared_constants_1.SUPER_ADMIN_USER_IDENTIFIER,
            superadminPassword: shared_constants_1.SUPER_ADMIN_USER_PASSWORD,
        });
        fs_extra_1.default.writeFileSync(path_1.default.join(root, 'README.md'), rootReadmeContent);
        // Copy root .gitignore
        await fs_extra_1.default.copyFile(templatePath('root-gitignore.template'), path_1.default.join(root, '.gitignore'));
        // Create server package.json
        const serverPackageJsonContents = {
            name: 'server',
            version: constants_1.DEFAULT_PROJECT_VERSION,
            private: true,
            scripts: getServerPackageScripts(),
        };
        fs_extra_1.default.writeFileSync(path_1.default.join(serverRoot, 'package.json'), JSON.stringify(serverPackageJsonContents, null, 2) + os_1.default.EOL);
    }
    else {
        // Single project structure (original behavior)
        const packageJsonContents = {
            name: appName,
            version: constants_1.DEFAULT_PROJECT_VERSION,
            private: true,
            scripts: getServerPackageScripts(),
        };
        fs_extra_1.default.writeFileSync(path_1.default.join(root, 'package.json'), JSON.stringify(packageJsonContents, null, 2) + os_1.default.EOL);
        fs_extra_1.default.ensureDirSync(path_1.default.join(root, 'src'));
    }
    setupSpinner.stop(`Created ${picocolors_1.default.green('package.json')}`);
    // Download storefront if needed
    if (includeStorefront) {
        const storefrontSpinner = (0, prompts_1.spinner)();
        storefrontSpinner.start(`Downloading Next.js storefront...`);
        try {
            await (0, helpers_1.downloadAndExtractStorefront)(storefrontRoot);
            // Update storefront package.json name and dev script port
            const storefrontPackageJsonPath = path_1.default.join(storefrontRoot, 'package.json');
            const storefrontPackageJson = await fs_extra_1.default.readJson(storefrontPackageJsonPath);
            storefrontPackageJson.name = 'storefront';
            if ((_a = storefrontPackageJson.scripts) === null || _a === void 0 ? void 0 : _a.dev) {
                storefrontPackageJson.scripts.dev = `next dev --port ${storefrontPort}`;
            }
            await fs_extra_1.default.writeJson(storefrontPackageJsonPath, storefrontPackageJson, { spaces: 2 });
            // Generate storefront .env.local from template
            const storefrontEnvTemplate = await fs_extra_1.default.readFile(templatePath('storefront-env.hbs'), 'utf-8');
            const storefrontEnvContent = handlebars_1.default.compile(storefrontEnvTemplate)({
                serverPort: port,
                storefrontPort,
                name: appName,
                revalidationSecret: (0, crypto_1.randomBytes)(32).toString('base64'),
            });
            fs_extra_1.default.writeFileSync(path_1.default.join(storefrontRoot, '.env.local'), storefrontEnvContent);
            storefrontSpinner.stop(`Downloaded Next.js storefront`);
        }
        catch (e) {
            storefrontSpinner.stop(picocolors_1.default.red(`Failed to download storefront`));
            (0, logger_1.log)(e.message, { level: 'verbose' });
            (0, prompts_1.outro)(picocolors_1.default.red(`Failed to download storefront: ${e.message}`));
            process.exit(1);
        }
    }
    // Install dependencies
    const { dependencies, devDependencies } = (0, helpers_1.getDependencies)(dbType, `@${packageJson.version}`);
    // Install server dependencies
    await installDependenciesWithSpinner({
        dependencies,
        logLevel,
        cwd: serverRoot,
        spinnerMessage: `Installing ${dependencies[0]} + ${dependencies.length - 1} more dependencies`,
        successMessage: `Successfully installed ${dependencies.length} dependencies`,
        failureMessage: 'Failed to install dependencies. Please try again.',
    });
    if (devDependencies.length) {
        await installDependenciesWithSpinner({
            dependencies: devDependencies,
            isDevDependencies: true,
            logLevel,
            cwd: serverRoot,
            spinnerMessage: `Installing ${devDependencies[0]} + ${devDependencies.length - 1} more dev dependencies`,
            successMessage: `Successfully installed ${devDependencies.length} dev dependencies`,
            failureMessage: 'Failed to install dev dependencies. Please try again.',
        });
    }
    if (includeStorefront) {
        // Install storefront dependencies
        const storefrontInstalled = await installDependenciesWithSpinner({
            dependencies: [],
            logLevel,
            cwd: storefrontRoot,
            spinnerMessage: 'Installing storefront dependencies...',
            successMessage: 'Installed storefront dependencies',
            failureMessage: 'Failed to install storefront dependencies',
            warnOnFailure: true,
        });
        if (!storefrontInstalled) {
            (0, logger_1.log)('You may need to run npm install in the storefront directory manually.', { level: 'info' });
        }
    }
    const scaffoldSpinner = (0, prompts_1.spinner)();
    scaffoldSpinner.start(`Generating app scaffold`);
    // We add this pause so that the above output is displayed before the
    // potentially lengthy file operations begin, which can prevent that
    // from displaying and thus make the user think that the process has hung.
    await (0, promises_1.setTimeout)(constants_1.SCAFFOLD_DELAY_MS);
    const srcPathScript = (fileName) => path_1.default.join(serverRoot, 'src', `${fileName}.ts`);
    if (!includeStorefront) {
        fs_extra_1.default.ensureDirSync(path_1.default.join(serverRoot, 'src'));
    }
    const configFile = srcPathScript('vendure-config');
    try {
        await fs_extra_1.default
            .writeFile(configFile, configSource)
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, '.env'), envSource))
            .then(() => fs_extra_1.default.writeFile(srcPathScript('environment.d'), envDtsSource))
            .then(() => fs_extra_1.default.writeFile(srcPathScript('index'), indexSource))
            .then(() => fs_extra_1.default.writeFile(srcPathScript('index-worker'), indexWorkerSource))
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'README.md'), readmeSource))
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'Dockerfile'), dockerfileSource))
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'docker-compose.yml'), dockerComposeSource))
            .then(() => fs_extra_1.default.ensureDir(path_1.default.join(serverRoot, 'src/plugins')))
            .then(() => fs_extra_1.default.copyFile(assetPath('gitignore.template'), path_1.default.join(serverRoot, '.gitignore')))
            .then(() => fs_extra_1.default.copyFile(assetPath('tsconfig.template.json'), path_1.default.join(serverRoot, 'tsconfig.json')))
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'tsconfig.dashboard.json'), tsconfigDashboardSource))
            .then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'vite.config.mts'), viteConfigSource))
            .then(() => createDirectoryStructure(serverRoot))
            .then(() => copyEmailTemplates(serverRoot));
    }
    catch (e) {
        (0, prompts_1.outro)(picocolors_1.default.red(`Failed to create app scaffold: ${e.message}`));
        process.exit(1);
    }
    scaffoldSpinner.stop(`Generated app scaffold`);
    if (mode === 'quick' && dbType === 'postgres') {
        (0, helpers_1.cleanUpDockerResources)(name);
        await (0, helpers_1.startPostgresDatabase)(serverRoot);
    }
    const populateSpinner = (0, prompts_1.spinner)();
    populateSpinner.start(`Initializing your new Vendure server`);
    // We want to display a set of tips and instructions to the user
    // as the initialization process is running because it can take
    // a few minutes to complete.
    const tips = [
        populateProducts
            ? 'We are populating sample data so that you can start testing right away'
            : 'We are setting up your Vendure server',
        ...constants_1.TIPS_WHILE_WAITING,
    ];
    let tipIndex = 0;
    let timer;
    function displayTip() {
        populateSpinner.message(tips[tipIndex]);
        tipIndex++;
        if (tipIndex >= tips.length) {
            // skip the intro tips if looping
            tipIndex = 3;
        }
        timer = setTimeout(displayTip, constants_1.TIP_INTERVAL_MS);
    }
    timer = setTimeout(displayTip, constants_1.TIP_INTERVAL_MS);
    // Change to serverRoot so that ts-node can correctly resolve modules.
    // In monorepo mode, dependencies are hoisted to the root node_modules,
    // but ts-node needs to be anchored in the server directory for proper
    // module resolution and to find the tsconfig.json.
    process.chdir(serverRoot);
    // register ts-node so that the config file can be loaded
    // We use transpileOnly to skip type checking during bootstrap, as the
    // complex module resolution with npm workspaces and ESM packages can
    // cause false TypeScript errors. Type checking happens when users run
    // their own build/dev commands.
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    require((0, helpers_1.resolvePackageRootDir)('ts-node', serverRoot)).register({
        project: path_1.default.join(serverRoot, 'tsconfig.json'),
        transpileOnly: true,
    });
    let superAdminCredentials;
    try {
        const { populate } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core', serverRoot), 'cli', 'populate')}`).then(s => __importStar(require(s)));
        const { bootstrap, DefaultLogger, LogLevel, JobQueueService } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core', serverRoot), 'dist', 'index')}`).then(s => __importStar(require(s)));
        const { config } = await Promise.resolve(`${configFile}`).then(s => __importStar(require(s)));
        const assetsDir = path_1.default.join(__dirname, '../assets');
        superAdminCredentials = config.authOptions.superadminCredentials;
        const initialDataPath = path_1.default.join(assetsDir, 'initial-data.json');
        const vendureLogLevel = logLevel === 'info' || logLevel === 'silent'
            ? LogLevel.Error
            : logLevel === 'verbose'
                ? LogLevel.Verbose
                : LogLevel.Info;
        const bootstrapFn = async () => {
            var _a;
            await (0, helpers_1.checkDbConnection)(config.dbConnectionOptions, serverRoot);
            const _app = await bootstrap(Object.assign(Object.assign({}, config), { apiOptions: Object.assign(Object.assign({}, ((_a = config.apiOptions) !== null && _a !== void 0 ? _a : {})), { port }), dbConnectionOptions: Object.assign(Object.assign({}, config.dbConnectionOptions), { synchronize: true }), logger: new DefaultLogger({ level: vendureLogLevel }), importExportOptions: {
                    importAssetsDir: path_1.default.join(assetsDir, 'images'),
                } }));
            await _app.get(JobQueueService).start();
            return _app;
        };
        const app = await populate(bootstrapFn, initialDataPath, populateProducts ? path_1.default.join(assetsDir, 'products.csv') : undefined);
        // Pause to ensure the worker jobs have time to complete.
        if (isCi) {
            (0, logger_1.log)('[CI] Pausing before close...');
        }
        await (0, promises_1.setTimeout)(isCi ? constants_1.CI_PAUSE_BEFORE_CLOSE_MS : constants_1.NORMAL_PAUSE_BEFORE_CLOSE_MS);
        await app.close();
        if (isCi) {
            (0, logger_1.log)('[CI] Pausing after close...');
            await (0, promises_1.setTimeout)(constants_1.CI_PAUSE_AFTER_CLOSE_MS);
        }
        populateSpinner.stop(`Server successfully initialized${populateProducts ? ' and populated' : ''}`);
        clearTimeout(timer);
        /**
         * This is currently disabled because I am running into issues actually getting the server
         * to quite properly in response to a SIGINT.
         * This means that the server runs, but cannot be ended, without forcefully
         * killing the process.
         *
         * Once this has been resolved, the following code can be re-enabled by
         * setting `autoRunServer` to `true`.
         */
        const autoRunServer = false;
        if (mode === 'quick' && autoRunServer) {
            // In quick-start mode, we want to now run the server and open up
            // a browser window to the Dashboard.
            try {
                const dashboardUrl = `http://localhost:${port}/dashboard`;
                const quickStartInstructions = [
                    'Use the following credentials to log in to the Dashboard:',
                    `Username: ${picocolors_1.default.green((_b = config.authOptions.superadminCredentials) === null || _b === void 0 ? void 0 : _b.identifier)}`,
                    `Password: ${picocolors_1.default.green((_c = config.authOptions.superadminCredentials) === null || _c === void 0 ? void 0 : _c.password)}`,
                    `Open your browser and navigate to: ${picocolors_1.default.green(dashboardUrl)}`,
                    '',
                ];
                (0, prompts_1.note)(quickStartInstructions.join('\n'));
                const npmCommand = os_1.default.platform() === 'win32' ? 'npm.cmd' : 'npm';
                let quickStartProcess;
                try {
                    quickStartProcess = (0, node_child_process_1.spawn)(npmCommand, ['run', 'dev'], {
                        cwd: root,
                        stdio: 'inherit',
                    });
                }
                catch (e) {
                    /* empty */
                }
                // process.stdin.resume();
                process.on('SIGINT', function () {
                    displayOutro({
                        root,
                        name,
                        superAdminCredentials,
                        includeStorefront,
                        serverPort: port,
                        storefrontPort,
                    });
                    quickStartProcess === null || quickStartProcess === void 0 ? void 0 : quickStartProcess.kill('SIGINT');
                    process.exit(0);
                });
                // Give enough time for the server to get up and running
                // before opening the window.
                await (0, promises_1.setTimeout)(constants_1.AUTO_RUN_DELAY_MS);
                try {
                    await (0, open_1.default)(dashboardUrl, {
                        newInstance: true,
                    });
                }
                catch (e) {
                    /* empty */
                }
            }
            catch (e) {
                (0, logger_1.log)(picocolors_1.default.red(`Failed to start the server: ${e.message}`), {
                    newline: 'after',
                    level: 'verbose',
                });
            }
        }
        else {
            clearTimeout(timer);
            displayOutro({
                root,
                name,
                superAdminCredentials,
                includeStorefront,
                serverPort: port,
                storefrontPort,
            });
            process.exit(0);
        }
    }
    catch (e) {
        (0, logger_1.log)(e.toString());
        (0, prompts_1.outro)(picocolors_1.default.red(`Failed to initialize server. Please try again.`));
        process.exit(1);
    }
}
/**
 * Returns the standard npm scripts for the server package.json.
 */
function getServerPackageScripts() {
    return {
        'dev:server': 'ts-node ./src/index.ts',
        'dev:worker': 'ts-node ./src/index-worker.ts',
        'dev:dashboard': 'vite --clearScreen false',
        dev: 'concurrently --kill-others npm:dev:*',
        build: 'tsc',
        'build:dashboard': 'vite build',
        'start:server': 'node ./dist/index.js',
        'start:worker': 'node ./dist/index-worker.js',
        start: 'concurrently npm:start:*',
    };
}
/**
 * Installs dependencies with a spinner, handling success/failure messaging.
 * Returns true if installation succeeded, false otherwise.
 */
async function installDependenciesWithSpinner(installOptions) {
    const { dependencies, isDevDependencies = false, logLevel, cwd, spinnerMessage, successMessage, failureMessage, warnOnFailure = false, } = installOptions;
    const installSpinner = (0, prompts_1.spinner)();
    installSpinner.start(spinnerMessage);
    try {
        await (0, helpers_1.installPackages)({ dependencies, isDevDependencies, logLevel, cwd });
        installSpinner.stop(successMessage);
        return true;
    }
    catch (e) {
        if (warnOnFailure) {
            installSpinner.stop(picocolors_1.default.yellow(`Warning: ${failureMessage}`));
            return false;
        }
        else {
            (0, prompts_1.outro)(picocolors_1.default.red(failureMessage));
            process.exit(1);
        }
    }
}
// eslint-disable-next-line @typescript-eslint/no-shadow
function displayOutro(outroOptions) {
    var _a, _b;
    const { root, name, superAdminCredentials, includeStorefront, serverPort = constants_1.SERVER_PORT, storefrontPort = constants_1.STOREFRONT_PORT, } = outroOptions;
    const startCommand = 'npm run dev';
    const identifier = (_a = superAdminCredentials === null || superAdminCredentials === void 0 ? void 0 : superAdminCredentials.identifier) !== null && _a !== void 0 ? _a : shared_constants_1.SUPER_ADMIN_USER_IDENTIFIER;
    const password = (_b = superAdminCredentials === null || superAdminCredentials === void 0 ? void 0 : superAdminCredentials.password) !== null && _b !== void 0 ? _b : shared_constants_1.SUPER_ADMIN_USER_PASSWORD;
    // Common footer for both modes
    const commonFooter = [
        `\n`,
        `Use the following credentials to log in:`,
        `Username: ${picocolors_1.default.green(identifier)}`,
        `Password: ${picocolors_1.default.green(password)}`,
        '\n',
        '➡️ Docs: https://docs.vendure.io',
        '➡️ Discord community: https://vendure.io/community',
        '➡️ Star us on GitHub:',
        '   https://github.com/vendure-ecommerce/vendure',
    ];
    let nextSteps;
    if (includeStorefront) {
        nextSteps = [
            `Your new Vendure project was created!`,
            picocolors_1.default.gray(root),
            `\n`,
            `This is a monorepo with the following apps:`,
            `  ${picocolors_1.default.cyan('apps/server')}     - Vendure backend`,
            `  ${picocolors_1.default.cyan('apps/storefront')} - Next.js frontend`,
            `\n`,
            `Next, run:`,
            picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`cd ${name}`)),
            picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`${startCommand}`)),
            `\n`,
            `This will start both the server and storefront.`,
            `\n`,
            `Access points:`,
            `  Dashboard:  ${picocolors_1.default.green(`http://localhost:${serverPort}/dashboard`)}`,
            `  Storefront: ${picocolors_1.default.green(`http://localhost:${storefrontPort}`)}`,
            ...commonFooter,
        ];
    }
    else {
        nextSteps = [
            `Your new Vendure server was created!`,
            picocolors_1.default.gray(root),
            `\n`,
            `Next, run:`,
            picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`cd ${name}`)),
            picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`${startCommand}`)),
            `\n`,
            `This will start the server in development mode.`,
            `\n`,
            `To run the Dashboard, in a new terminal navigate to your project directory and run:`,
            picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`npx vite`)),
            `\n`,
            `To access the Dashboard, open your browser and navigate to:`,
            picocolors_1.default.green(`http://localhost:${serverPort}/dashboard`),
            ...commonFooter,
        ];
    }
    (0, prompts_1.note)(nextSteps.join('\n'), picocolors_1.default.green('Setup complete!'));
    (0, prompts_1.outro)(`Happy hacking!`);
}
/**
 * Run some initial checks to ensure that it is okay to proceed with creating
 * a new Vendure project in the given location.
 */
function runPreChecks(name) {
    if (typeof name === 'undefined') {
        (0, logger_1.log)(picocolors_1.default.red(`Please specify the project directory:`));
        (0, logger_1.log)(`  ${picocolors_1.default.cyan(commander_1.program.name())} ${picocolors_1.default.green('<project-directory>')}`, { newline: 'after' });
        (0, logger_1.log)('For example:');
        (0, logger_1.log)(`  ${picocolors_1.default.cyan(commander_1.program.name())} ${picocolors_1.default.green('my-vendure-app')}`);
        process.exit(1);
        return false;
    }
    const root = path_1.default.resolve(name);
    try {
        fs_extra_1.default.ensureDirSync(name);
    }
    catch (e) {
        (0, logger_1.log)(picocolors_1.default.red(`Could not create project directory ${name}: ${e.message}`));
        return false;
    }
    if (!(0, helpers_1.isSafeToCreateProjectIn)(root, name)) {
        process.exit(1);
    }
    return true;
}
/**
 * Generate the default directory structure for a new Vendure project
 */
async function createDirectoryStructure(root) {
    await fs_extra_1.default.ensureDir(path_1.default.join(root, 'static', 'email', 'test-emails'));
    await fs_extra_1.default.ensureDir(path_1.default.join(root, 'static', 'assets'));
}
/**
 * Copy the email templates into the app
 */
async function copyEmailTemplates(root) {
    const emailPackageDirname = (0, helpers_1.resolvePackageRootDir)('@vendure/email-plugin', root);
    const templateDir = path_1.default.join(emailPackageDirname, 'templates');
    try {
        await fs_extra_1.default.copy(templateDir, path_1.default.join(root, 'static', 'email', 'templates'));
    }
    catch (err) {
        (0, logger_1.log)(picocolors_1.default.red('Failed to copy email templates.'));
        (0, logger_1.log)(err);
        process.exit(0);
    }
}
//# sourceMappingURL=create-vendure-app.js.map